diff --git a/.ci/compute_projects.py b/.ci/compute_projects.py index c3cf714ce6c10..2dc5629328457 100644 --- a/.ci/compute_projects.py +++ b/.ci/compute_projects.py @@ -19,6 +19,7 @@ PROJECT_DEPENDENCIES = { "llvm": set(), "clang": {"llvm"}, + "CIR": {"clang", "mlir"}, "bolt": {"clang", "lld", "llvm"}, "clang-tools-extra": {"clang", "llvm"}, "compiler-rt": {"clang", "lld"}, @@ -55,6 +56,7 @@ ".ci": { "llvm", "clang", + "CIR", "lld", "lldb", "bolt", @@ -128,6 +130,7 @@ "lldb": "check-lldb", "llvm": "check-llvm", "clang": "check-clang", + "CIR": "check-clang-cir", "bolt": "check-bolt", "lld": "check-lld", "flang": "check-flang", @@ -141,6 +144,23 @@ RUNTIMES = {"libcxx", "libcxxabi", "libunwind", "compiler-rt", "libc"} +# Meta projects are projects that need explicit handling but do not reside +# in their own top level folder. To add a meta project, the start of the path +# for the metaproject should be mapped to the name of the project below. +# Multiple paths can map to the same metaproject. +META_PROJECTS = { + ("clang", "lib", "CIR"): "CIR", + ("clang", "test", "CIR"): "CIR", + ("clang", "include", "clang", "CIR"): "CIR", + ("*", "docs"): "docs", + ("llvm", "utils", "gn"): "gn", + (".github", "workflows", "premerge.yaml"): ".ci", + ("third-party",): ".ci", +} + +# Projects that should not run any tests. These need to be metaprojects. +SKIP_PROJECTS = ["docs", "gn"] + def _add_dependencies(projects: Set[str], runtimes: Set[str]) -> Set[str]: projects_with_dependents = set(projects) @@ -233,21 +253,34 @@ def _compute_runtimes_to_build( return _exclude_projects(runtimes_to_build, platform) +def _path_matches(matcher: tuple[str], file_path: tuple[str]) -> bool: + if len(file_path) < len(matcher): + return False + for match_part, file_part in zip(matcher, file_path): + if match_part == "*" or file_part == "*": + continue + if match_part != file_part: + return False + return True + + +def _get_modified_projects_for_file(modified_file: str) -> Set[str]: + modified_projects = set() + path_parts = pathlib.Path(modified_file).parts + for meta_project_files in META_PROJECTS.keys(): + if _path_matches(meta_project_files, path_parts): + meta_project = META_PROJECTS[meta_project_files] + if meta_project in SKIP_PROJECTS: + return set() + modified_projects.add(meta_project) + modified_projects.add(pathlib.Path(modified_file).parts[0]) + return modified_projects + + def _get_modified_projects(modified_files: list[str]) -> Set[str]: modified_projects = set() for modified_file in modified_files: - path_parts = pathlib.Path(modified_file).parts - # Exclude files in the docs directory. They do not impact an test - # targets and there is a separate workflow used for ensuring the - # documentation builds. - if len(path_parts) > 2 and path_parts[1] == "docs": - continue - # Exclude files for the gn build. We do not test it within premerge - # and changes occur often enough that they otherwise take up - # capacity. - if len(path_parts) > 3 and path_parts[:3] == ("llvm", "utils", "gn"): - continue - modified_projects.add(pathlib.Path(modified_file).parts[0]) + modified_projects.update(_get_modified_projects_for_file(modified_file)) return modified_projects @@ -267,6 +300,13 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]: runtimes_check_targets_needs_reconfig = _compute_project_check_targets( runtimes_to_test_needs_reconfig ) + + # CIR is used as a pseudo-project in this script. It is built as part of the + # clang build, but it requires an explicit option to enable. We set that + # option here, and remove it from the projects_to_build list. + enable_cir = "ON" if "CIR" in projects_to_build else "OFF" + projects_to_build.discard("CIR") + # We use a semicolon to separate the projects/runtimes as they get passed # to the CMake invocation and thus we need to use the CMake list separator # (;). We use spaces to separate the check targets as they end up getting @@ -279,6 +319,7 @@ def get_env_variables(modified_files: list[str], platform: str) -> Set[str]: "runtimes_check_targets_needs_reconfig": " ".join( sorted(runtimes_check_targets_needs_reconfig) ), + "enable_cir": enable_cir, } diff --git a/.ci/compute_projects_test.py b/.ci/compute_projects_test.py index 6299931e1ec34..11c4aea9b4e35 100644 --- a/.ci/compute_projects_test.py +++ b/.ci/compute_projects_test.py @@ -1,7 +1,7 @@ # 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 -"""Does some stuff.""" +"""Tests for compute_projects.py""" import unittest @@ -104,6 +104,10 @@ def test_clang(self): env_variables["runtimes_check_targets_needs_reconfig"], "check-cxx check-cxxabi check-unwind", ) + self.assertEqual( + env_variables["enable_cir"], + "OFF", + ) def test_clang_windows(self): env_variables = compute_projects.get_env_variables( @@ -126,6 +130,32 @@ def test_clang_windows(self): env_variables["runtimes_check_targets_needs_reconfig"], "check-cxx check-cxxabi check-unwind", ) + self.assertEqual(env_variables["enable_cir"], "OFF") + + def test_cir(self): + env_variables = compute_projects.get_env_variables( + ["clang/lib/CIR/CMakeLists.txt"], "Linux" + ) + self.assertEqual( + env_variables["projects_to_build"], + "clang;clang-tools-extra;lld;llvm;mlir", + ) + self.assertEqual( + env_variables["project_check_targets"], + "check-clang check-clang-cir check-clang-tools", + ) + self.assertEqual( + env_variables["runtimes_to_build"], "compiler-rt;libcxx;libcxxabi;libunwind" + ) + self.assertEqual( + env_variables["runtimes_check_targets"], + "check-compiler-rt", + ) + self.assertEqual( + env_variables["runtimes_check_targets_needs_reconfig"], + "check-cxx check-cxxabi check-unwind", + ) + self.assertEqual(env_variables["enable_cir"], "ON") def test_bolt(self): env_variables = compute_projects.get_env_variables( @@ -158,6 +188,7 @@ def test_mlir(self): self.assertEqual(env_variables["runtimes_to_build"], "") self.assertEqual(env_variables["runtimes_check_targets"], "") self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + self.assertEqual(env_variables["enable_cir"], "OFF") def test_flang(self): env_variables = compute_projects.get_env_variables( @@ -168,10 +199,11 @@ def test_flang(self): self.assertEqual(env_variables["runtimes_to_build"], "") self.assertEqual(env_variables["runtimes_check_targets"], "") self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + self.assertEqual(env_variables["enable_cir"], "OFF") def test_invalid_subproject(self): env_variables = compute_projects.get_env_variables( - ["third-party/benchmark/CMakeLists.txt"], "Linux" + ["llvm-libgcc/CMakeLists.txt"], "Linux" ) self.assertEqual(env_variables["projects_to_build"], "") self.assertEqual(env_variables["project_check_targets"], "") @@ -237,7 +269,7 @@ def test_ci(self): ) self.assertEqual( env_variables["project_check_targets"], - "check-bolt check-clang check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", + "check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", ) self.assertEqual( env_variables["runtimes_to_build"], @@ -276,6 +308,66 @@ def test_clang_tools_extra(self): self.assertEqual(env_variables["runtimes_check_targets"], "check-libc") self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + def test_premerge_workflow(self): + env_variables = compute_projects.get_env_variables( + [".github/workflows/premerge.yaml"], "Linux" + ) + self.assertEqual( + env_variables["projects_to_build"], + "bolt;clang;clang-tools-extra;flang;libclc;lld;lldb;llvm;mlir;polly", + ) + self.assertEqual( + env_variables["project_check_targets"], + "check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", + ) + self.assertEqual( + env_variables["runtimes_to_build"], + "compiler-rt;libc;libcxx;libcxxabi;libunwind", + ) + self.assertEqual( + env_variables["runtimes_check_targets"], + "check-compiler-rt check-libc", + ) + self.assertEqual( + env_variables["runtimes_check_targets_needs_reconfig"], + "check-cxx check-cxxabi check-unwind", + ) + + def test_other_github_workflow(self): + env_variables = compute_projects.get_env_variables( + [".github/workflows/docs.yml"], "Linux" + ) + self.assertEqual(env_variables["projects_to_build"], "") + self.assertEqual(env_variables["project_check_targets"], "") + self.assertEqual(env_variables["runtimes_to_build"], "") + self.assertEqual(env_variables["runtimes_check_targets"], "") + self.assertEqual(env_variables["runtimes_check_targets_needs_reconfig"], "") + + def test_third_party_benchmark(self): + env_variables = compute_projects.get_env_variables( + ["third-party/benchmark/CMakeLists.txt"], "Linux" + ) + self.assertEqual( + env_variables["projects_to_build"], + "bolt;clang;clang-tools-extra;flang;libclc;lld;lldb;llvm;mlir;polly", + ) + self.assertEqual( + env_variables["project_check_targets"], + "check-bolt check-clang check-clang-cir check-clang-tools check-flang check-lld check-lldb check-llvm check-mlir check-polly", + ) + self.assertEqual( + env_variables["runtimes_to_build"], + "compiler-rt;libc;libcxx;libcxxabi;libunwind", + ) + self.assertEqual( + env_variables["runtimes_check_targets"], + "check-compiler-rt check-libc", + ) + self.assertEqual( + env_variables["runtimes_check_targets_needs_reconfig"], + "check-cxx check-cxxabi check-unwind", + ) + if __name__ == "__main__": unittest.main() diff --git a/.ci/metrics/metrics.py b/.ci/metrics/metrics.py index 143e6ab4cf46a..26fdeef1913ab 100644 --- a/.ci/metrics/metrics.py +++ b/.ci/metrics/metrics.py @@ -1,3 +1,13 @@ +# 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 +"""Collects Github metrics and uploads them to Grafana. + +This script contains machinery that will pull metrics periodically from Github +about workflow runs. It will upload the collected metrics to the specified +Grafana instance. +""" + import collections import datetime import github diff --git a/.ci/metrics/metrics_test.py b/.ci/metrics/metrics_test.py new file mode 100644 index 0000000000000..259e55f817939 --- /dev/null +++ b/.ci/metrics/metrics_test.py @@ -0,0 +1,75 @@ +# 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 +"""Tests for metrics.py""" + +from dataclasses import dataclass +import requests +import unittest +import unittest.mock + +import metrics + + +class TestMetrics(unittest.TestCase): + def test_upload_gauge_metric(self): + """Test that we can upload a gauge metric correctly. + + Also verify that we pass around parameters like API keys and user IDs + correctly to the HTTP POST request. + """ + test_metrics = [metrics.GaugeMetric("gauge_test", 5, 1000)] + return_value = requests.Response() + return_value.status_code = 204 + with unittest.mock.patch( + "requests.post", return_value=return_value + ) as post_mock: + metrics.upload_metrics(test_metrics, "test_userid", "test_api_key") + self.assertSequenceEqual(post_mock.call_args.args, [metrics.GRAFANA_URL]) + self.assertEqual( + post_mock.call_args.kwargs["data"], "gauge_test value=5 1000" + ) + self.assertEqual( + post_mock.call_args.kwargs["auth"], ("test_userid", "test_api_key") + ) + + def test_upload_job_metric(self): + """Test that we can upload a job metric correctly.""" + test_metrics = [ + metrics.JobMetrics("test_job", 5, 10, 1, 1000, 7, "test_workflow") + ] + return_value = requests.Response() + return_value.status_code = 204 + with unittest.mock.patch( + "requests.post", return_value=return_value + ) as post_mock: + metrics.upload_metrics(test_metrics, "test_userid", "test_aoi_key") + self.assertEqual( + post_mock.call_args.kwargs["data"], + "test_job queue_time=5,run_time=10,status=1 1000", + ) + + def test_upload_unknown_metric(self): + """Test we report an error if we encounter an unknown metric type.""" + + @dataclass + class FakeMetric: + fake_data: str + + test_metrics = [FakeMetric("test")] + + with self.assertRaises(ValueError): + metrics.upload_metrics(test_metrics, "test_userid", "test_api_key") + + def test_bad_response_code(self): + """Test that we gracefully handle HTTP response errors.""" + test_metrics = [metrics.GaugeMetric("gauge_test", 5, 1000)] + return_value = requests.Response() + return_value.status_code = 403 + # Just assert that we continue running here and do not raise anything. + with unittest.mock.patch("requests.post", return_value=return_value) as _: + metrics.upload_metrics(test_metrics, "test_userid", "test_api_key") + + +if __name__ == "__main__": + unittest.main() diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 8d1faab13986c..6db24d894eb73 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -21,12 +21,7 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" INSTALL_DIR="${BUILD_DIR}/install" rm -rf "${BUILD_DIR}" -ccache --zero-stats - -if [[ -n "${CLEAR_CACHE:-}" ]]; then - echo "clearing cache" - ccache --clear -fi +sccache --zero-stats mkdir -p artifacts/reproducers @@ -36,7 +31,7 @@ export CLANG_CRASH_DIAGNOSTICS_DIR=`realpath artifacts/reproducers` function at-exit { retcode=$? - ccache --print-stats > artifacts/ccache_stats.txt + sccache --show-stats > artifacts/sccache_stats.txt cp "${BUILD_DIR}"/.ninja_log artifacts/.ninja_log cp "${BUILD_DIR}"/test-results.*.xml artifacts/ || : @@ -53,6 +48,7 @@ targets="${2}" runtimes="${3}" runtime_targets="${4}" runtime_targets_needs_reconfig="${5}" +enable_cir="${6}" lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests" @@ -72,13 +68,15 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -G Ninja \ -D CMAKE_PREFIX_PATH="${HOME}/.local" \ -D CMAKE_BUILD_TYPE=Release \ + -D CLANG_ENABLE_CIR=${enable_cir} \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ -D LLVM_LIT_ARGS="${lit_args}" \ -D LLVM_ENABLE_LLD=ON \ -D CMAKE_CXX_FLAGS=-gmlt \ - -D LLVM_CCACHE_BUILD=ON \ + -D CMAKE_C_COMPILER_LAUNCHER=sccache \ + -D CMAKE_CXX_COMPILER_LAUNCHER=sccache \ -D LIBCXX_CXX_ABI=libcxxabi \ -D MLIR_ENABLE_BINDINGS_PYTHON=ON \ -D LLDB_ENABLE_PYTHON=ON \ diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 176350fac604c..50a741677d734 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -21,11 +21,6 @@ BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" rm -rf "${BUILD_DIR}" -if [[ -n "${CLEAR_CACHE:-}" ]]; then - echo "clearing sccache" - rm -rf "$SCCACHE_DIR" -fi - sccache --zero-stats function at-exit { retcode=$? diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c951a24fc8d31..3b8abd35b58c9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,140 +11,4 @@ # See https://llvm.org/docs/DeveloperPolicy.html#maintainers as well as the # Maintainers.* files in the the respective subproject directories. -/libcxx/ @llvm/reviewers-libcxx -/libcxxabi/ @llvm/reviewers-libcxxabi -/libunwind/ @llvm/reviewers-libunwind -/runtimes/ @llvm/reviewers-libcxx - -/llvm/lib/Analysis/BasicAliasAnalysis.cpp @nikic -/llvm/lib/Analysis/InstructionSimplify.cpp @nikic -/llvm/lib/Analysis/LazyValueInfo.cpp @nikic -/llvm/lib/Analysis/ScalarEvolution.cpp @nikic -/llvm/lib/Analysis/ValueTracking.cpp @nikic -/llvm/lib/IR/ConstantRange.cpp @nikic -/llvm/lib/IR/Core.cpp @nikic -/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @nikic -/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @nikic -/llvm/lib/Transforms/InstCombine/ @nikic - -/clang/test/CXX/drs/ @Endilll -/clang/www/cxx_dr_status.html @Endilll -/clang/www/make_cxx_dr_status @Endilll - -/clang/include/clang/CIR @lanza @bcardosolopes -/clang/lib/CIR @lanza @bcardosolopes -/clang/tools/cir-* @lanza @bcardosolopes - -/lldb/ @JDevlieghere - -# MLIR Interfaces. -/mlir/include/mlir/Interfaces/TilingInterface.* @MaheshRavishankar @nicolasvasilache -/mlir/lib/Interfaces/TilingInterface.* @MaheshRavishankar @nicolasvasilache -/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.* @matthias-springer -/mlir/lib/Interfaces/ValueBoundsOpInterface.* @matthias-springer -/mlir/**/ValueBoundsOpInterfaceImpl.* @matthias-springer -/mlir/include/mlir/Interfaces/RuntimeVerifiableOpInterface.* @matthias-springer -/mlir/lib/Interfaces/RuntimeVerifiableOpInterface.* @matthias-springer -/mlir/**/RuntimeVerifiableOpInterfaceImpl.* @matthias-springer -/mlir/include/mlir/Interfaces/SubsetOpInterface.* @matthias-springer -/mlir/lib/Interfaces/SubsetOpInterface.* @matthias-springer -/mlir/**/SubsetOpInterfaceImpl.* @matthias-springer -/mlir/include/mlir/Interfaces/DestinationStyleOpInterface.* @matthias-springer -/mlir/lib/Interfaces/DestinationStyleOpInterface.* @matthias-springer - -# Bufferization Dialect in MLIR. -/mlir/include/mlir/Dialect/Bufferization @matthias-springer -/mlir/lib/Dialect/Bufferization @matthias-springer -/mlir/**/BufferizableOpInterfaceImpl.* @matthias-springer -/mlir/Dialect/*/Transforms/Bufferize.cpp @matthias-springer - -# Linalg Dialect in MLIR. -/mlir/include/mlir/Dialect/Linalg @dcaballe @nicolasvasilache @rengolin -/mlir/lib/Dialect/Linalg @dcaballe @nicolasvasilache @rengolin -/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @dcaballe @MaheshRavishankar @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @hanhanW @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp @dcaballe @hanhanW @nicolasvasilache -/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @banach-space @dcaballe @hanhanW @nicolasvasilache @Groverkss - -# MemRef Dialect in MLIR. -/mlir/lib/Dialect/MemRef/Transforms/EmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache - -# Vector Dialect in MLIR. -/mlir/**/*AMX* @aartbik @dcaballe -/mlir/**/*Neon* @banach-space @dcaballe @nicolasvasilache -/mlir/**/*SME* @banach-space @dcaballe @nicolasvasilache -/mlir/**/*SVE* @banach-space @dcaballe @nicolasvasilache -/mlir/**/*VectorInterfaces* @dcaballe @nicolasvasilache -/mlir/**/*VectorToSCF* @banach-space @dcaballe @matthias-springer @nicolasvasilache -/mlir/**/*VectorToLLVM* @banach-space @dcaballe @nicolasvasilache -/mlir/**/*X86Vector* @aartbik @dcaballe @nicolasvasilache -/mlir/include/mlir/Dialect/Vector @banach-space @dcaballe @nicolasvasilache @Groverkss -/mlir/include/mlir/Dialect/Vector/IR @kuhar -/mlir/lib/Dialect/Vector @banach-space @dcaballe @nicolasvasilache @Groverkss -/mlir/lib/Dialect/Vector/Transforms/* @banach-space @dcaballe @hanhanW @nicolasvasilache -/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @banach-space @dcaballe @MaheshRavishankar @nicolasvasilache -/mlir/**/*EmulateNarrowType* @dcaballe @hanhanW - -# Presburger library in MLIR -/mlir/**/*Presburger* @Groverkss @Superty - -# Tensor Dialect in MLIR. -/mlir/lib/Dialect/Tensor/IR/TensorTilingInterfaceImpl.cpp @hanhanW @nicolasvasilache -/mlir/lib/Dialect/Tensor/Transforms/* @hanhanW @nicolasvasilache - -# Transform Dialect in MLIR. -/mlir/include/mlir/Dialect/Transform/* @ftynse @nicolasvasilache -/mlir/lib/Dialect/Transform/* @ftynse @nicolasvasilache -/mlir/**/*TransformOps* @ftynse @nicolasvasilache - -# SPIR-V Dialect in MLIR. -/mlir/**/SPIRV/ @antiagainst @kuhar -/mlir/**/SPIRVTo*/ @antiagainst @kuhar -/mlir/**/*ToSPIRV/ @antiagainst @kuhar -/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp @antiagainst @kuhar - -# MLIR Sparsifier. -/mlir/**/*SparseTensor*/ @aartbik @PeimingLiu @yinying-lisa-li @matthias-springer - -# MLIR NVGPU Dialect -/mlir/**/NVGPU*/ @grypp -/mlir/test/**/CUDA/ @grypp - -# MLIR NVVM Dialect in MLIR -/mlir/**/LLVMIR/**/BasicPtxBuilderInterface* @grypp -/mlir/**/NVVM* @grypp - -# MLIR Index Dialect -/mlir/**/Index* @mogball - -# MLIR Python Bindings -/mlir/test/python/ @ftynse @makslevental @stellaraccident -/mlir/python/ @ftynse @makslevental @stellaraccident - -# MLIR Mem2Reg/SROA -/mlir/**/Transforms/Mem2Reg.* @moxinilian -/mlir/**/Transforms/SROA.* @moxinilian - -# BOLT -/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @yota9 @paschalis-mpeis - -# Bazel build system. -/utils/bazel/ @rupprecht @keith @aaronmondal - -# InstallAPI and TextAPI -/llvm/**/TextAPI/ @cyndyishida -/clang/**/InstallAPI/ @cyndyishida -/clang/tools/clang-installapi/ @cyndyishida - -# ExtractAPI -/clang/**/ExtractAPI @daniel-grumberg @QuietMisdreavus - -# DWARFLinker, dwarfutil, dsymutil -/llvm/**/DWARFLinker/ @JDevlieghere -/llvm/**/dsymutil/ @JDevlieghere -/llvm/**/llvm-dwarfutil/ @JDevlieghere - -# libclang/Python bindings -/clang/bindings/python @DeinAlptraum +* @intel-staging/npu-compiler-llvm-maintain diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..355ebf0ad697c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +## Summary +> Please add a short but exhaustive summary why you think your pull request is useful + +## JIRA ticket + +* E-xxxxx + +## Related PR in NPU Compiler and/or OpenVINO repository with sub-module update + +* PR-xxx + +### Other related tickets +> List tickets for additional work, eg, something was found during review but you agreed to address it in another Jira + +* E-xxxxx diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 03748938700e3..0000000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,4 +0,0 @@ -When performing a code review, pay close attention to code modifying a function's -control flow. Could the change result in the corruption of performance profile -data? Could the change result in invalid debug information, in particular for -branches and calls? diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 8c1dfd39b82c4..0000000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,18 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" - groups: - github-actions: - patterns: - - "*" - - package-ecosystem: "pip" - directory: "/llvm/docs" - schedule: - interval: "monthly" - groups: - llvm-docs-requirements: - patterns: - - "*" diff --git a/.github/new-issues-labeler.yml b/.github/new-issues-labeler.yml deleted file mode 100644 index ee7506c1366ef..0000000000000 --- a/.github/new-issues-labeler.yml +++ /dev/null @@ -1,38 +0,0 @@ -'clang': - - '/\bclang(?!\-)\b/i' - -'clang-format': - - '/\bclang-format/i' - -'clang-tidy': - - '/\bclang-tidy/i' - -'libc++': - - '/libc[+x]{2}(?!\-)/i' - -'libc++abi': - - '/libc[+x]{2}-?abi/i' - -'libc': - - '/\blibc(?![-+])\b/i' - -'flang': - - '/\bflang(?!\-)\b/i' - -'lld': - - '/\blld(?!\-)\b/i' - -'mlir': - - '/\bmlir(?!\-)\b/i' - -'bolt': - - '/\bbolt(?!\-)\b/i' - -'infra:commit-access-request': - - '/Request Commit Access/' - -'false-positive': - - '\bfalse[- ]positive\b' - -'false-negative': - - '\bfalse[- ]negative\b' diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml deleted file mode 100644 index b05e9c6c56ed0..0000000000000 --- a/.github/new-prs-labeler.yml +++ /dev/null @@ -1,1107 +0,0 @@ -BOLT: - - bolt/**/* - -ClangIR: - - clang/include/clang/CIR/**/* - - clang/lib/CIR/**/* - - clang/tools/cir-*/**/* - - clang/test/CIR/**/* - -clang:bytecode: - - clang/docs/ConstantInterpreter.rst - - clang/lib/AST/ByteCode/**/* - - clang/test/AST/ByteCode/**/* - - clang/unittests/AST/ByteCode/**/* - -clang:dataflow: - - clang/include/clang/Analysis/FlowSensitive/**/* - - clang/lib/Analysis/FlowSensitive/**/* - - clang/unittests/Analysis/FlowSensitive/**/* - - clang/docs/DataFlowAnalysisIntro.md - - clang/docs/DataFlowAnalysisIntroImages/**/* - -clang:frontend: - - clang/lib/AST/**/* - - clang/include/clang/AST/**/* - - clang/lib/Basic/**/* - - clang/include/clang/Basic/**/* - - clang/lib/Interpreter/**/* - - clang/include/clang/Interpreter/**/* - - clang/lib/Lex/**/* - - clang/include/clang/Lex/**/* - - clang/lib/Parse/**/* - - clang/include/clang/Parse/**/* - - clang/lib/Sema/**/* - - clang/include/clang/Sema/**/* - -clang:headers: - - clang/lib/Headers/**/* - -compiler-rt: - - compiler-rt/**/* - -flang: - - flang/**/* - -flang:frontend: - - flang/Parser/**/* - - flang/Evaluate/**/* - - flang/Semantics/**/* - -HLSL: - - clang/*HLSL*/**/* - - clang/**/*HLSL* - - llvm/**/Frontend/HLSL/**/* - -lld: - - lld/**/* - -llvm-lit: - - llvm/utils/lit/**/* - -PGO: - - llvm/**/ProfileData/**/* - - llvm/**/SampleProfile* - - llvm/**/CodeGen/MIRSampleProfile* - - llvm/lib/Transforms/Instrumentation/CGProfile.cpp - - llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp - - llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp - - llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp - - llvm/lib/Transforms/Instrumentation/PGO* - - llvm/lib/Transforms/Instrumentation/ValueProfile* - - llvm/test/Instrumentation/InstrProfiling/**/* - - llvm/test/Transforms/PGOProfile/**/* - - llvm/test/Transforms/SampleProfile/**/* - - llvm/**/llvm-profdata/**/* - - llvm/**/llvm-profgen/**/* - -vectorizers: - - llvm/lib/Transforms/Vectorize/**/* - - llvm/include/llvm/Transforms/Vectorize/**/* - -# IMPORTED FROM CODEOWNERS -LTO: - - llvm/*/LTO/** - - llvm/*/Linker/** - - llvm/*/ThinLTO/** - - llvm/lib/Transforms/*/FunctionImport* - - llvm/tools/gold/** - -mc: - - llvm/*/MC/** - -clang:driver: - - clang/*/Driver/** - -compiler-rt:asan: - - compiler-rt/lib/asan/** - - compiler-rt/include/sanitizer/asan_interface.h - - compiler-rt/test/asan/** - - compiler-rt/lib/asan_abi/** - - compiler-rt/test/asan_abi/** - -compiler-rt:builtins: - - compiler-rt/lib/builtins/** - - compiler-rt/test/builtins/** - -compiler-rt:cfi: - - compiler-rt/lib/cfi/** - - compiler-rt/test/cfi/** - -compiler-rt:fuzzer: - - compiler-rt/lib/fuzzer/** - - compiler-rt/include/fuzzer/** - - compiler-rt/test/fuzzer/** - -compiler-rt:hwasan: - - compiler-rt/lib/hwasan/** - - compiler-rt/include/sanitizer/hwasan_interface.h - - compiler-rt/test/hwasan/** - -compiler-rt:lsan: - - compiler-rt/lib/lsan/** - - compiler-rt/include/sanitizer/lsan_interface.h - - compiler-rt/test/lsan/** - -compiler-rt:msan: - - compiler-rt/lib/msan/** - - compiler-rt/include/sanitizer/msan_interface.h - - compiler-rt/test/msan/** - -compiler-rt:sanitizer: - - llvm/lib/Transforms/Instrumentation/*Sanitizer* - - compiler-rt/lib/interception/** - - compiler-rt/lib/*san*/** - - compiler-rt/include/sanitizer/** - - compiler-rt/test/*san*/** - - compiler-rt/lib/fuzzer/** - - compiler-rt/include/fuzzer/** - - compiler-rt/test/fuzzer/** - - compiler-rt/lib/scudo/** - - compiler-rt/test/scudo/** - -compiler-rt:scudo: - - compiler-rt/lib/scudo/** - - compiler-rt/test/scudo/** - -compiler-rt:tsan: - - compiler-rt/lib/tsan/** - - compiler-rt/include/sanitizer/tsan_interface.h - - compiler-rt/include/sanitizer/tsan_interface_atomic.h - - compiler-rt/test/tsan/** - -compiler-rt:ubsan: - - compiler-rt/lib/ubsan/** - - compiler-rt/include/sanitizer/ubsan_interface.h - - compiler-rt/test/ubsan/** - - compiler-rt/lib/ubsan_minimal/** - - compiler-rt/test/ubsan_minimal/** - -xray: - - llvm/tools/llvm-xray/** - - compiler-rt/*/xray/** - - clang/include/clang/Basic/XRay* - - clang/lib/Basic/XRay* - - compiler-rt/*/xray/** - - llvm/include/llvm/XRay/** - - llvm/lib/XRay/** - - llvm/tools/llvm-xray/** - - llvm/unittests/XRay/** - - compiler-rt/*/xray/** - -clang:codegen: - - clang/lib/CodeGen/** - - clang/include/clang/CodeGen/** - -mlir: - - mlir/** - -mlir:core: - - mlir/include/mlir/Support/** - - mlir/lib/Support/** - - mlir/include/mlir/Parser/** - - mlir/lib/Parser/** - - mlir/include/mlir/IR/** - - mlir/lib/IR/** - - mlir/include/mlir/Bytecode/** - - mlir/lib/Bytecode/** - - mlir/include/mlir/AsmParser/** - - mlir/lib/AsmParser/** - - mlir/include/mlir/Pass/** - - mlir/lib/Pass/** - - mlir/include/mlir/Tools/** - - mlir/lib/Tools/** - - mlir/include/mlir/Reducer/** - - mlir/lib/Reducer/** - - mlir/include/mlir/Transforms/** - - mlir/lib/Transforms/** - - mlir/include/mlir/Debug/** - - mlir/lib/Debug/** - - mlir/tools/** - -mlir:ods: - - mlir/TableGen/** - - mlir/tblgen/** - - mlir/include/mlir/IR/*.td - -mlir:bindings: - - mlir/Bindings/** - -mlir:gpu: - - mlir/**/*GPU*/** - -mlir:amdgpu: - - mlir/**/AMDGPU/** - -mlir:amx: - - mlir/**/AMX/** - -mlir:affine: - - mlir/**/Affine/** - -mlir:arith: - - mlir/**/Arith/** - -mlir:neon: - - mlir/**/ArmNeon/** - -mlir:sme: - - mlir/**/ArmSME/** - -mlir:sve: - - mlir/**/ArmSVE/** - -mlir:async: - - mlir/**/Async/** - - mlir/**/Async/** - -mlir:bufferization: - - mlir/**/Bufferization/** - -mlir:complex: - - mlir/**/Complex/** - -mlir:cf: - - mlir/**/ControlFlow/** - -mlir:dlti: - - mlir/**/DLTI/** - -mlir:emitc: - - mlir/**/*EmitC*/** - - mlir/lib/Target/Cpp/** - -mlir:func: - - mlir/**/Func/** - -mlir:irdl: - - mlir/**/IRDL/** - -mlir:index: - - mlir/**/Index/** - -mlir:llvm: - - mlir/**/LLVM* - - mlir/**/LLVM*/** - -mlir:linalg: - - mlir/**/*linalg/** - - mlir/**/*Linalg/** - -mlir:mlprogram: - - mlir/**/MLProgram/** - -mlir:math: - - mlir/**/Math/** - -mlir:memref: - - mlir/**/MemRef/** - -mlir:nvgpu: - - mlir/**/NVGPU/** - -mlir:openacc: - - mlir/**/*OpenACC* - - mlir/**/*OpenACC*/** - -mlir:openmp: - - mlir/**/*OpenMP* - - mlir/**/*OpenMP*/** - -mlir:pdl: - - mlir/**/PDL/** - -mlir:quant: - - mlir/**/Quant/** - -mlir:scf: - - mlir/**/SCF/** - -mlir:spirv: - - mlir/**/SPIRV/** - - mlir/**/SPIRVTo*/** - - mlir/**/*ToSPIRV/** - - mlir/tools/mlir-spirv-cpu-runner/** - - mlir/tools/mlir-vulkan-runner/** - - mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp - -mlir:shape: - - mlir/**/Shape/** - -mlir:sparse: - - mlir/**/SparseTensor/** - -mlir:tensor: - - mlir/**/Tensor/** - -mlir:tosa: - - mlir/**/*Tosa*/** - -mlir:ub: - - mlir/**/UB/** - -mlir:vector: - - mlir/**/*Vector/** - -mlir:execution-engine: - - mlir/**/ExecutionEngine/** - -mlir:presburger: - - mlir/**/*Presburger*/** - -mlir:python: - - mlir/python/**/* - -mlir:vectorops: - - mlir/**/Vector/**/* - -coroutines: - - clang/docs/DebuggingCoroutines.rst - - clang/lib/Sema/SemaCoroutine.cpp - - clang/lib/CodeGen/CGCoroutine.cpp - - clang/test/CodeGenCoroutines/** - - llvm/docs/Coroutines.rst - - llvm/include/llvm/Transforms/Coroutines/** - - llvm/lib/Transforms/Coroutines/** - - llvm/test/Transforms/Coroutines/* - -clang:modules: - - clang/docs/StandardCPlusPlusModules.rst - - clang/include/clang/AST/AbstractBasicReader.h - - clang/include/clang/AST/AbstractBasicWriter.h - - clang/include/clang/AST/AbstractTypeReader.h - - clang/include/clang/AST/AbstractTypeWriter.h - - clang/include/clang/AST/PropertiesBase.td - - clang/include/clang/AST/ODRHash.h - - clang/include/clang/AST/TypeProperties.td - - clang/include/clang/Basic/Module.h - - clang/include/clang/Frontend/PrecompiledPreamble.h - - clang/include/clang/Lex/ModuleLoader.h - - clang/include/clang/Lex/ModuleMap.h - - clang/include/clang/Serialization/** - - clang/lib/AST/ODRHash.cpp - - clang/lib/AST/StmtProfile.cpp - - clang/lib/Basic/Module.cpp - - clang/lib/Frontend/ModuleDependencyCollector.cpp - - clang/lib/Frontend/PrecompiledPreamble.cpp - - clang/lib/Lex/ModuleMap.cpp - - clang/lib/Sema/SemaModule.cpp - - clang/lib/Serialization/** - - clang/test/CXX/module/** - - clang/test/Modules/** - - clang/unittests/Serialization/* - -clang-tidy: - - clang-tools-extra/clang-tidy/** - - clang-tools-extra/docs/clang-tidy/** - - clang-tools-extra/test/clang-tidy/** - -clang-tools-extra: - - clang-tools-extra/** - -tools:llvm-mca: - - llvm/tools/llvm-mca/** - - llvm/include/llvm/MCA/** - - llvm/lib/MCA/** - -clang: - - any: - - clang/** - - '!clang/**/Format/**' - - '!clang/tools/clang-format/**' - -testing-tools: - - llvm/include/llvm/FileCheck/** - - llvm/lib/FileCheck/** - - llvm/test/FileCheck/** - - llvm/unittests/FileCheck/** - - llvm/utils/lit/** - - llvm/utils/split-file/** - - llvm/utils/not/** - - llvm/utils/count/** - - llvm/utils/FileCheck/** - - llvm/docs/CommandGuide/FileCheck.rst - - llvm/docs/CommandGuide/lit.rst - - llvm/docs/TestingGuide.rst - - llvm/test/Other/FileCheck-space.txt - - llvm/utils/UpdateTestChecks/** - - llvm/utils/update*_test_checks.py - -debuginfo: - - clang/lib/CodeGen/CGDebugInfo.* - - llvm/include/llvm/BinaryFormat/Dwarf.* - - llvm/include/llvm/CodeGen/*Debug*.* - - llvm/include/llvm/DebugInfo/** - - llvm/include/llvm/Debuginfod/** - - llvm/include/llvm/Frontend/Debug/** - - llvm/include/llvm/IR/Debug*.* - - llvm/include/llvm/Object/*Debug*.* - - llvm/include/llvm/ObjectYAML/*Debug*.* - - llvm/include/llvm/Transforms/Utils/*Debug*.* - - llvm/include/llvm-c/DebugInfo.h - - llvm/lib/BinaryFormat/Dwarf.cpp - - llvm/lib/CodeGen/AsmPrinter/*Debug*.* - - llvm/lib/CodeGen/AsmPrinter/Dwarf*.* - - llvm/lib/CodeGen/AsmPrinter/DIE*.* - - llvm/lib/CodeGen/LiveDebugValues/** - - llvm/lib/CodeGen/*Debug*.* - - llvm/lib/CodeGen/DwarfEHPrepare.cpp - - llvm/lib/DebugInfo/** - - llvm/lib/Debuginfod/** - - llvm/lib/DWARFLinkerParallel/** - - llvm/lib/IR/Debug*.cpp - - llvm/lib/MC/MCDwarf.cpp - - llvm/lib/Transforms/Utils/*Debug*.* - - llvm/test/DebugInfo/** - - llvm/test/tools/dsymutil/** - - llvm/test/tools/llvm-debuginfo-analyzer/** - - llvm/test/tools/llvm-debuginfod/** - - llvm/test/tools/llvm-debuginfod-find/** - - llvm/test/tools/llvm-dwarfdump/** - - llvm/test/tools/llvm-dwarfutil/** - - llvm/test/tools/llvm-dwp/** - - llvm/test/tools/llvm-gsymutil/** - - llvm/test/tools/llvm-pdbuti/** - - llvm/tools/dsymutil/** - - llvm/tools/llvm-debuginfo-analyzer/** - - llvm/tools/llvm-debuginfod/** - - llvm/tools/llvm-debuginfod-find/** - - llvm/tools/llvm-dwarfdump/** - - llvm/tools/llvm-dwarfutil/** - - llvm/tools/llvm-dwp/** - - llvm/tools/llvm-gsymutil/** - - llvm/tools/llvm-pdbutil/** - -github:workflow: - - .github/workflows/** - -cmake: - - cmake/** - - llvm/cmake/** - - runtimes/** - -flang:driver: - - flang/tools/flang-driver/** - - flang/unittests/Frontend/** - - flang/lib/FrontendTool/** - - flang/lib/Frontend/** - - flang/include/flang/Frontend/** - - flang/include/flang/FrontendTool/** - - flang/test/Driver/** - -backend:m68k: - - llvm/lib/Target/M68k/** - - clang/lib/Basic/Targets/M68k.* - - clang/lib/CodeGen/Targets/M68k.cpp - - llvm/test/CodeGen/M68k/** - - llvm/test/MC/Disassembler/M68k/** - - llvm/test/MC/M68k/** - -libc++: - - libcxx/** - - .github/workflows/libcxx-* - -libc++abi: - - libcxxabi/** - -libunwind: - - libunwind/** - -objectyaml: - - llvm/include/llvm/ObjectYAML/** - - llvm/lib/ObjectYAML/** - - llvm/test/tools/obj2yaml/** - - llvm/test/tools/yaml2obj/** - - llvm/tools/obj2yaml/** - - llvm/tools/yaml2obj/** - -clang:analysis: - - clang/include/clang/Analysis/** - - clang/lib/Analysis/** - -clang:static analyzer: - - clang/include/clang/StaticAnalyzer/** - - clang/lib/StaticAnalyzer/** - - clang/tools/scan-build/** - - clang/utils/analyzer/** - - clang/docs/analyzer/** - - clang/test/Analysis/** - -pgo: - - llvm/lib/Transforms/Instrumentation/CGProfile.cpp - - llvm/lib/Transforms/Instrumentation/ControlHeightReduction.cpp - - llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp - - llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp - - llvm/lib/Transforms/Instrumentation/PGO* - - llvm/lib/Transforms/Instrumentation/ValueProfile* - - llvm/test/Instrumentation/InstrProfiling/** - - llvm/test/Transforms/PGOProfile/** - - compiler-rt/lib/profile/** - - compiler-rt/lib/memprof/** - - compiler-rt/test/profile/** - - compiler-rt/test/memprof/** - - llvm/tools/llvm-profdata/** - - llvm/tools/llvm-profgen/** - - llvm/test/tools/llvm-profdata/** - - llvm/test/tools/llvm-profgen/** - - llvm/unittests/ProfileData/* - -openacc: - - flang/**/OpenACC/** - - flang/include/flang/Lower/OpenACC.h - - flang/docs/OpenACC.md - - flang/lib/Parser/openacc-parsers.cpp - - flang/lib/Lower/OpenACC.cpp - - llvm/**/Frontend/OpenACC/** - - llvm/unittests/Frontend/OpenACCTest.cpp - - mlir/test/Target/LLVMIR/openacc-llvm.mlir - - mlir/**/*OpenACC/** - -flang:runtime: - - flang/runtime/** - -flang:parser: - - flang/**/Parser/** - -flang:semantics: - - flang/**/Evaluate/** - - flang/**/Semantics/** - -flang:fir-hlfir: - - flang/**/Lower/** - - flang/**/Optimizer/** - -flang:codegen: - - flang/**/CodeGen/** - -llvm:codegen: - - llvm/lib/CodeGen/* - - llvm/lib/CodeGen/MIRParser/* - - llvm/lib/CodeGen/LiveDebugValues/* - - llvm/lib/CodeGen/AsmPrinter/* - -llvm:globalisel: - - llvm/**/GlobalISel/** - - llvm/utils/TableGen/GlobalISel* - -function-specialization: - - llvm/include/llvm/Transforms/Utils/SCCPSolver.h - - llvm/lib/Transforms/Utils/SCCPSolver.cpp - - llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h - - llvm/lib/Transforms/IPO/FunctionSpecialization.cpp - - llvm/test/Transforms/FunctionSpecialization/* - -libc: - - libc/** - - utils/bazel/llvm-project-overlay/libc/** - -clang-format: - - clang/**/Format/** - - clang/tools/clang-format/** - -flang:openmp: - - flang/test/**/OpenMP/** - - flang/lib/Lower/OpenMP.cpp - - flang/lib/Semantics/resolve-directives.cpp - - flang/lib/Semantics/check-omp-structure.cpp - - flang/lib/Optimizer/Transforms/OMP* - - flang/test/Fir/convert-to-llvm-openmp-and-fir.fir - - flang/test/Lower/OpenMP/** - - flang/test/Transforms/omp* - - mlir/**/*OpenMP* - - mlir/test/Target/LLVMIR/openmp* - - llvm/lib/Frontend/OpenMP/** - - llvm/include/llvm/Frontend/OpenMP/** - - llvm/unittests/Frontend/OpenMP* - -llvm:ir: - - llvm/lib/IR/** - - llvm/include/llvm/IR/** - - llvm/docs/LangRef.rst - - llvm/unittests/IR/** - -llvm:SandboxIR: - - llvm/lib/SandboxIR/** - - llvm/include/llvm/SandboxIR/** - - llvm/docs/SandboxIR.md - - llvm/unittests/SandboxIR/** - -llvm:analysis: - - llvm/lib/Analysis/** - - llvm/include/llvm/Analysis/** - - llvm/test/Analysis/** - - llvm/unittests/Analysis/** - -llvm:adt: - - llvm/**/ADT/* - -llvm:support: - - llvm/**/Support/** - -llvm:transforms: - - llvm/lib/Transforms/** - - llvm/include/llvm/Transforms/** - - llvm/test/Transforms/** - - llvm/unittests/Transforms/** - -llvm:instcombine: - - llvm/lib/Analysis/InstructionSimplify.cpp - - llvm/lib/Transforms/InstCombine/** - - llvm/include/llvm/Transforms/InstCombine/ - - llvm/include/llvm/Analysis/InstructionSimplify.h - - llvm/test/Transforms/InstCombine/** - - llvm/test/Transforms/InstSimplify/** - -llvm:vectorcombine: - - llvm/lib/Transforms/Vectorize/VectorCombine.cpp - - llvm/test/Transforms/VectorCombine/** - -clangd: - - clang-tools-extra/clangd/** - -hlsl: - - clang/test/ParserHLSL/** - - clang/test/SemaHLSL/** - - clang/test/AST/HLSL/** - - clang/test/CodeGenHLSL/** - - clang/cmake/caches/HLSL.cmake - - clang/include/clang/Basic/HLSL*.h - - clang/include/clang/Sema/HLSL*.h - - clang/docs/HLSL/** - - clang/lib/Driver/ToolChains/HLSL* - - clang/lib/Parse/ParseHLSL.cpp - - clang/lib/Sema/HLSLExternalSemaSource.cpp - - clang/lib/Sema/SemaHLSL.cpp - - clang/lib/CodeGen/CGHLSLRuntime.* - - clang/lib/CodeGen/CGHLSLBuiltins.cpp - - llvm/include/llvm/Frontend/HLSL/** - - llvm/lib/Frontend/HLSL/** - -llvm:SelectionDAG: - - llvm/include/llvm/CodeGen/SelectionDAG*.h - - llvm/include/llvm/CodeGen/SDNodeProperties.td - - llvm/include/llvm/Target/TargetSelectionDAG.td - - llvm/lib/CodeGen/SelectionDAG/** - - llvm/utils/TableGen/CodeGenDAG* - - llvm/utils/TableGen/DAGISel* - - llvm/include/llvm/CodeGen/DAGCombine.h - - llvm/include/llvm/CodeGen/ISDOpcodes.h - -backend:DirectX: - - '**/*DirectX*' - - '**/*DXIL*' - - '**/*dxil*' - - '**/*DirectX*/**' - - '**/*DXIL*/**' - - '**/*dxil*/**' - - '**/*DXContainer*' - - '**/*DXContainer*/**' - - clang/lib/Sema/SemaDirectX.cpp - - clang/include/clang/Sema/SemaDirectX.h - - clang/include/clang/Basic/BuiltinsDirectX.td - - clang/lib/CodeGen/TargetBuiltins/DirectX.cpp - - clang/test/CodeGenDirectX/** - - clang/test/SemaDirectX/** - -backend:SPIR-V: - - clang/lib/Driver/ToolChains/SPIRV.* - - clang/lib/Sema/SemaSPIRV.cpp - - clang/include/clang/Sema/SemaSPIRV.h - - clang/include/clang/Basic/BuiltinsSPIRV.td - - clang/test/CodeGenSPIRV/** - - clang/test/SemaSPIRV/** - - llvm/lib/Target/SPIRV/** - - llvm/test/CodeGen/SPIRV/** - - llvm/test/Frontend/HLSL/** - - llvm/docs/SPIRVUsage.rst - -mlgo: - - llvm/lib/Analysis/ML* - - llvm/include/llvm/Analysis/ML* - - llvm/lib/Analysis/*Runner.cpp - - llvm/include/llvm/Analysis/*Runner.h - - llvm/unittests/Analysis/ML* - - llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp - - llvm/lib/Analysis/TrainingLogger.cpp - - llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h - - llvm/include/llvm/Analysis/Utils/TrainingLogger.h - - llvm/test/Analysis/FunctionPropertiesAnalysis/* - - llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp - - llvm/test/Transforms/inline/ML/** - - llvm/lib/CodeGen/ML* - - llvm/unittests/CodeGen/ML* - - llvm/test/CodeGen/MLRegAlloc/** - - llvm/utils/mlgo-utils/** - - llvm/docs/MLGO.rst - - llvm/include/llvm/Analysis/IR2Vec.h - - llvm/lib/Analysis/IR2Vec.cpp - - llvm/lib/Analysis/models/** - - llvm/test/Analysis/IR2Vec/** - -tools:llvm-exegesis: - - llvm/tools/llvm-exegesis/** - - llvm/test/tools/llvm-exegesis/** - - llvm/unittests/tools/llvm-exegesis/** - -tools:llvm-reduce: - - llvm/tools/llvm-reduce/** - -platform:windows: - - lld/COFF/** - - clang/lib/Driver/MSVC.cpp - - clang/lib/Driver/MinGW.cpp - - llvm/lib/DebugInfo/CodeView/** - - llvm/lib/DebugInfo/PDB/** - - llvm/lib/WindowsDriver/** - - llvm/lib/Support/Windows/** - - llvm/lib/BinaryFormat/COFF.cpp - -llvm:regalloc: - - llvm/**/CodeGen/CalcSpillWeights* - - llvm/**/CodeGen/InlineSpiller* - - llvm/**/CodeGen/InterferenceCache* - - llvm/**/CodeGen/LiveInterval* - - llvm/**/CodeGen/LiveRange* - - llvm/**/CodeGen/LiveReg* - - llvm/**/CodeGen/LiveVariables* - - llvm/**/CodeGen/MachineCopyPropagation* - - llvm/**/CodeGen/PHIElimination* - - llvm/**/CodeGen/ProcessImplicitDefs.cpp - - llvm/**/CodeGen/Register* - - llvm/**/CodeGen/RegUsage* - - llvm/**/CodeGen/RenameIndependentSubregs.cpp - - llvm/**/CodeGen/SlotIndexes.h - - llvm/**/CodeGen/SpillPlacement* - - llvm/**/CodeGen/SplitKit* - - llvm/**/CodeGen/VirtRegMap.h - - llvm/include/PBQP/** - - llvm/include/PBQPRAConstraint.h - - llvm/include/llvm/CodeGen/Spiller.h - - llvm/**/*RegAlloc - -lldb: - - lldb/** - -lldb-dap: - - lldb/tools/lldb-dap/** - -backend:AMDGPU: - - '**/*amdgpu*' - - '**/*AMDGPU*' - - '**/*amdgpu*/**' - - '**/*AMDGPU*/**' - -backend:NVPTX: - - 'llvm/**/*nvvm*' - - 'llvm/**/*NVVM*' - - 'llvm/**/*nvptx*' - - 'llvm/**/*NVPTX*' - - 'llvm/**/*nvvm*/**' - - 'llvm/**/*NVVM*/**' - - 'llvm/**/*nvptx*/**' - - 'llvm/**/*NVPTX*/**' - -backend:MIPS: - - '**/*mips*' - - '**/*Mips*' - - '**/*mips*/**' - - '**/*Mips*/**' - -backend:RISC-V: - - '**/*riscv*' - - '**/*RISCV*' - - '**/*riscv*/**' - - '**/*RISCV*/**' - -backend:Xtensa: - - '**/*xtensa*' - - '**/*Xtensa*' - - '**/*xtensa*/**' - - '**/*Xtensa*/**' - -lld:coff: - - lld/**/COFF/** - - lld/Common/** - -lld:elf: - - lld/**/ELF/** - - lld/Common/** - -lld:macho: - - lld/**/MachO/** - - lld/Common/** - -lld:wasm: - - lld/**/wasm/** - - lld/Common/** - -backend:ARC: - - llvm/lib/Target/ARC/** - - clang/lib/Basic/Targets/ARC.h - - clang/lib/Basic/Targets/ARC.cpp - - clang/lib/CodeGen/Targets/ARC.cpp - -backend:ARM: - - llvm/include/llvm/IR/IntrinsicsARM.td - - llvm/test/MC/ARM/** - - llvm/lib/Target/ARM/** - - llvm/test/CodeGen/ARM/** - - clang/lib/Basic/Targets/ARM* - - clang/lib/Driver/ToolChains/Arch/ARM.* - - clang/lib/CodeGen/Targets/ARM.cpp - - clang/include/clang/Basic/BuiltinsARM* - - llvm/test/MC/DisasemblerARM/** - - clang/include/clang/Sema/SemaARM.h - - clang/lib/Sema/SemaARM.cpp - -backend:AArch64: - - llvm/include/llvm/IR/IntrinsicsAArch64.td - - llvm/test/MC/AArch64/** - - llvm/lib/Target/AArch64/** - - llvm/test/CodeGen/AArch64/** - - clang/lib/Basic/Targets/AArch64* - - clang/lib/Driver/ToolChains/Arch/AArch64.* - - clang/lib/CodeGen/Targets/AArch64.cpp - - clang/include/clang/Basic/BuiltinsAArch64* - - llvm/test/MC/Disassembler/AArch64/** - - clang/include/clang/Sema/SemaARM.h - - clang/lib/Sema/SemaARM.cpp - -backend:CSKY: - - llvm/lib/Target/CSKY/** - - llvm/include/llvm/TargetParser/CSKYTargetParser.def - - llvm/include/llvm/TargetParser/CSKYTargetParser.h - - llvm/include/llvm/BinaryFormat/ELFRelocs/CSKY.def - - llvm/lib/TargetParser/CSKYTargetParser.cpp - - llvm/lib/Support/CSKYAttributes.cpp - - llvm/lib/Support/CSKYAttributeParser.cpp - - clang/lib/Basic/Targets/CSKY.h - - clang/lib/Basic/Targets/CSKY.cpp - - clang/lib/CodeGen/Targets/CSKY.cpp - - clang/lib/Driver/ToolChains/CSKY* - -backend:Hexagon: - - clang/include/clang/Basic/BuiltinsHexagon*.def - - clang/include/clang/Sema/SemaHexagon.h - - clang/lib/Basic/Targets/Hexagon.* - - clang/lib/CodeGen/Targets/Hexagon.cpp - - clang/lib/Driver/ToolChains/Hexagon.* - - clang/lib/Sema/SemaHexagon.cpp - - lld/ELF/Arch/Hexagon.cpp - - lldb/source/Plugins/ABI/Hexagon/** - - lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/** - - llvm/include/llvm/BinaryFormat/ELFRelocs/Hexagon.def - - llvm/include/llvm/IR/IntrinsicsHexagon* - - llvm/include/llvm/Support/Hexagon* - - llvm/lib/Support/Hexagon* - - llvm/lib/Target/Hexagon/** - - llvm/test/CodeGen/Hexagon/** - - llvm/test/CodeGen/*/Hexagon/** - - llvm/test/DebugInfo/*/Hexagon/** - - llvm/test/Transforms/*/Hexagon - - llvm/test/MC/Disassembler/Hexagon/** - - llvm/test/MC/Hexagon/** - - llvm/test/tools/llvm-objdump/ELF/Hexagon/** - -backend:Lanai: - - llvm/lib/Target/Lanai/** - - clang/lib/Basic/Targets/Lanai.h - - clang/lib/Basic/Targets/Lanai.cpp - - clang/lib/CodeGen/Targets/Lanai.cpp - - clang/lib/Driver/ToolChains/Lanai* - -backend:loongarch: - - llvm/include/llvm/IR/IntrinsicsLoongArch.td - - llvm/test/MC/LoongArch/** - - llvm/lib/Target/LoongArch/** - - llvm/test/CodeGen/LoongArch/** - - clang/lib/Basic/Targets/LoongArch* - - clang/lib/Driver/ToolChains/Arch/LoongArch.* - - clang/lib/CodeGen/Targets/LoongArch.cpp - - clang/include/clang/Basic/BuiltinsLoongArch* - - clang/include/clang/Sema/SemaLoongArch.h - - clang/lib/Sema/SemaLoongArch.cpp - -backend:MSP430: - - llvm/include/llvm/IR/IntrinsicsMSP430.td - - llvm/test/MC/MSP430/** - - llvm/lib/Target/MSP430/** - - llvm/test/CodeGen/MSP430/** - - clang/lib/Basic/Targets/MSP430* - - clang/lib/Driver/ToolChains/Arch/MSP430.* - - clang/lib/CodeGen/Targets/MSP430.cpp - - clang/include/clang/Basic/BuiltinsMSP430* - - llvm/test/MC/Disassembler/MSP430/** - -backend:Sparc: - - llvm/include/llvm/IR/IntrinsicsSparc.td - - llvm/test/MC/Sparc/** - - llvm/lib/Target/Sparc/** - - llvm/test/CodeGen/Sparc/** - - clang/lib/Basic/Targets/Sparc* - - clang/lib/Driver/ToolChains/Arch/Sparc.* - - clang/lib/CodeGen/Targets/Sparc.cpp - - clang/include/clang/Basic/BuiltinsSparc* - - llvm/test/MC/Disassembler/Sparc/** - -backend:WebAssembly: - - llvm/lib/Target/WebAssembly/** - - llvm/test/CodeGen/WebAssembly/** - - clang/lib/Basic/Targets/WebAssembly* - - clang/include/clang/Basic/BuiltinsWebAssembly.def - - clang/include/clang/Basic/WebAssemblyReferenceTypes.def - - clang/lib/CodeGen/Targets/WebAssembly* - - llvm/include/llvm/IR/IntinsicsWebAssembly.td - - llvm/include/llvm/Object/Wasm* - - llvm/lib/CodeGen/AsmPrinter/Wasm* - - llvm/lib/CodeGen/Wasm* - - llvm/lib/MC/MCParser/Wasm* - - llvm/lib/MC/Wasm* - - llvm/lib/ObjCopy/wasm/** - - llvm/lib/Object/Wasm* - - clang/lib/Driver/Toolchains/WebAssembly* - - clang/lib/Headers/wasm_simd128.h - - clang/test/CodeGen/WebAssembly/** - - clang/test/SemaCXX/*wasm* - - clang/test/Sema/*wasm* - - llvm/include/llvm/BinaryFormat/Wasm.h - - llvm/unittests/Target/WebAssembly/** - - llvm/test/DebugInfo/WebAssembly/** - - llvm/test/MC/WebAssembly/** - - clang/include/clang/Sema/SemaWasm.h - - clang/lib/Sema/SemaLoongWasm.cpp - -backend:X86: - - llvm/include/llvm/IR/IntrinsicsX86.td - - llvm/lib/Target/X86/** - - llvm/test/CodeGen/X86/** - - llvm/test/MC/X86/** - - llvm/test/MC/Disassembler/X86/** - - llvm/test/Analysis/CostModel/X86/** - - llvm/test/tools/llvm-mca/X86/** - - clang/lib/Basic/Targets/X86/** - - clang/lib/Driver/ToolChains/Arch/X86.* - - clang/lib/CodeGen/Targets/X86.* - - clang/lib/Headers/** - - clang/test/CodeGen/X86/** - - clang/include/clang/Basic/BuiltinsX86* - - llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h - - llvm/include/llvm/TargetParser/X86* - - llvm/lib/TargetParser/X86* - - llvm/utils/TableGen/X86* - - clang/include/clang/Sema/SemaX86.h - - clang/lib/Sema/SemaX86.cpp - -backend:PowerPC: - - llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC* - - llvm/include/llvm/BinaryFormat/XCOFF.h - - llvm/include/llvm/IR/IntrinsicsPowerPC.td - - llvm/lib/CodeGen/AsmPrinter/AIXException.cpp - - llvm/lib/Target/PowerPC/** - - llvm/test/Analysis/**/PowerPC/** - - llvm/test/CodeGen/PowerPC/** - - llvm/test/CodeGen/MIR/PowerPC/** - - llvm/test/DebugInfo/XCOFF/** - - llvm/test/DebugInfo/PowerPC/** - - llvm/test/LTO/PowerPC/** - - llvm/test/MC/Disassembler/PowerPC/** - - llvm/test/MC/PowerPC/** - - llvm/test/MC/XCOFF/** - - llvm/test/Transforms/**/PowerPC/** - - clang/include/clang/Basic/BuiltinsPPC.* - - clang/lib/Basic/Targets/PPC.* - - clang/lib/CodeGen/Targets/PPC.cpp - - clang/lib/Driver/ToolChains/PPC* - - clang/lib/Driver/ToolChains/AIX* - - clang/lib/Driver/ToolChains/Arch/PPC.* - - clang/test/CodeGen/PowerPC/** - - clang/include/clang/Sema/SemaPPC.h - - clang/lib/Sema/SemaPPC.cpp - -backend:SystemZ: - - llvm/include/llvm/BinaryFormat/ELFRelocs/SystemZ* - - llvm/include/llvm/BinaryFormat/GOFF.h - - llvm/include/llvm/IR/IntrinsicsSystemZ.td - - llvm/lib/Target/SystemZ/** - - llvm/test/Analysis/**/SystemZ/** - - llvm/test/CodeGen/SystemZ/** - - llvm/test/DebugInfo/SystemZ/** - - llvm/test/ExecutionEngine/**/SystemZ/** - - llvm/test/MC/Disassembler/SystemZ/** - - llvm/test/MC/GOFF/** - - llvm/test/MC/SystemZ/** - - llvm/test/Transforms/**/SystemZ/** - - clang/include/clang/Basic/BuiltinsSystemZ.* - - clang/lib/Basic/Targets/SystemZ.* - - clang/lib/CodeGen/Targets/SystemZ.cpp - - clang/lib/Driver/ToolChains/ZOS* - - clang/lib/Driver/ToolChains/Arch/SystemZ.* - - clang/test/CodeGen/SystemZ/** - - clang/include/clang/Sema/SemaSystemZ.h - - clang/lib/Sema/SemaSystemZ.cpp - -third-party:unittests: - - third-party/unittests/** - -third-party:benchmark: - - third-party/benchmark/** - -llvm:binary-utilities: - - llvm/docs/CommandGuide/llvm-* - - llvm/include/llvm/BinaryFormat/** - - llvm/include/llvm/DebugInfo/Symbolize/** - - llvm/include/llvm/ObjCopy/** - - llvm/include/llvm/Object/** - - llvm/lib/BinaryFormat/** - - llvm/lib/DebugInfo/Symbolize/** - - llvm/lib/ObjCopy/** - - llvm/lib/Object/** - - llvm/test/Object/** - - llvm/test/tools/llvm-ar/** - - llvm/test/tools/llvm-cxxfilt/** - - llvm/test/tools/llvm-nm/** - - llvm/test/tools/llvm-objcopy/** - - llvm/test/tools/llvm-objdump/** - - llvm/test/tools/llvm-readobj/** - - llvm/test/tools/llvm-size/** - - llvm/test/tools/llvm-strings/** - - llvm/test/tools/llvm-symbolizer/** - - llvm/tools/llvm-ar/** - - llvm/tools/llvm-cxxfilt/** - - llvm/tools/llvm-nm/** - - llvm/tools/llvm-objcopy/** - - llvm/tools/llvm-objdump/** - - llvm/tools/llvm-readobj/** - - llvm/tools/llvm-size/** - - llvm/tools/llvm-strings/** - - llvm/tools/llvm-symbolizer/** - -clang:openmp: - - clang/include/clang/Basic/OpenMP* - - clang/include/clang/AST/OpenMPClause.h - - clang/include/clang/AST/DeclOpenMP.h - - clang/include/clang/AST/ExprOpenMP.h - - clang/include/clang/AST/StmtOpenMP.h - - clang/lib/AST/DeclOpenMP.cpp - - clang/lib/AST/OpenMPClause.cpp - - clang/lib/AST/StmtOpenMP.cpp - - clang/lib/Headers/openmp_wrappers/** - - clang/lib/Parse/ParseOpenMP.cpp - - clang/lib/Basic/OpenMPKinds.cpp - - clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp - - clang/lib/Driver/ToolChains/AMDGPUOpenMP.h - - clang/lib/CodeGen/CgStmtOpenMP.cpp - - clang/lib/CodeGen/CGOpenMP* - - clang/lib/Sema/SemaOpenMP.cpp - - clang/test/OpenMP/** - - clang/test/AST/ast-dump-openmp-* - - llvm/lib/Frontend/OpenMP/** - - llvm/lib/Transforms/IPO/OpenMPOpt.cpp - - llvm/include/llvm/Frontend/OpenMP/** - - llvm/include/llvm/Transforms/IPO/OpenMPOpt.h - - llvm/unittests/Frontend/OpenMP* - - llvm/test/Transforms/OpenMP/** - -clang:as-a-library: - - clang/tools/libclang/** - - clang/bindings/** - - clang/include/clang-c/** - - clang/test/LibClang/** - - clang/unittest/libclang/** - -openmp:libomp: - - any: ['openmp/**', '!openmp/libomptarget/**'] - -openmp:libomptarget: - - any: ['openmp/**', '!openmp/runtime/**'] - -bazel: - - utils/bazel/** - -offload: - - offload/** - -tablegen: - - llvm/include/TableGen/** - - llvm/lib/TableGen/** - - llvm/utils/TableGen/** diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index ce34d2337e9c5..0000000000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1 +0,0 @@ -Github action workflows should be stored in this directory. diff --git a/.github/workflows/build-ci-container-windows.yml b/.github/workflows/build-ci-container-windows.yml deleted file mode 100644 index 59079f057d021..0000000000000 --- a/.github/workflows/build-ci-container-windows.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Build Windows CI Container - -permissions: - contents: read - -on: - push: - branches: - - main - paths: - - .github/workflows/build-ci-container-windows.yml - - '.github/workflows/containers/github-action-ci-windows/**' - pull_request: - branches: - - main - paths: - - .github/workflows/build-ci-container-windows.yml - - '.github/workflows/containers/github-action-ci-windows/**' - -jobs: - build-ci-container-windows: - if: github.repository_owner == 'llvm' - runs-on: windows-2022 - outputs: - container-name: ${{ steps.vars.outputs.container-name }} - container-name-tag: ${{ steps.vars.outputs.container-name-tag }} - container-filename: ${{ steps.vars.outputs.container-filename }} - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: .github/workflows/containers/github-action-ci-windows - - name: Write Variables - id: vars - run: | - $tag = [int64](Get-Date -UFormat %s) - $container_name="ghcr.io/$env:GITHUB_REPOSITORY_OWNER/ci-windows-2022" - echo "container-name=${container_name}" >> $env:GITHUB_OUTPUT - echo "container-name-tag=${container_name}:${tag}" >> $env:GITHUB_OUTPUT - echo "container-filename=ci-windows-${tag}.tar" >> $env:GITHUB_OUTPUT - - name: Build Container - working-directory: .github/workflows/containers/github-action-ci-windows - run: | - docker build -t ${{ steps.vars.outputs.container-name-tag }} . - - name: Save container image - run: | - docker save ${{ steps.vars.outputs.container-name-tag }} > ${{ steps.vars.outputs.container-filename }} - - name: Upload container image - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: container - path: ${{ steps.vars.outputs.container-filename }} - retention-days: 14 - - push-ci-container: - if: github.event_name == 'push' - needs: - - build-ci-container-windows - permissions: - packages: write - runs-on: windows-2022 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Download container - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: container - - name: Push Container - run: | - docker load -i ${{ needs.build-ci-container-windows.outputs.container-filename }} - docker tag ${{ needs.build-ci-container-windows.outputs.container-name-tag }} ${{ needs.build-ci-container-windows.outputs.container-name }}:latest - docker login -u ${{ github.actor }} -p $env:GITHUB_TOKEN ghcr.io - docker push ${{ needs.build-ci-container-windows.outputs.container-name-tag }} - docker push ${{ needs.build-ci-container-windows.outputs.container-name }}:latest diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml deleted file mode 100644 index 3159aae32ca51..0000000000000 --- a/.github/workflows/build-ci-container.yml +++ /dev/null @@ -1,119 +0,0 @@ -name: Build CI Container - -permissions: - contents: read - -on: - push: - branches: - - main - paths: - - .github/workflows/build-ci-container.yml - - '.github/workflows/containers/github-action-ci/**' - pull_request: - branches: - - main - paths: - - .github/workflows/build-ci-container.yml - - '.github/workflows/containers/github-action-ci/**' - -jobs: - build-ci-container: - if: github.repository_owner == 'llvm' - runs-on: ${{ matrix.runs-on }} - strategy: - matrix: - include: - # The arch names should match the names used on dockerhub. - # See https://github.com/docker-library/official-images#architectures-other-than-amd64 - - arch: amd64 - runs-on: depot-ubuntu-24.04-16 - - arch: arm64v8 - runs-on: depot-ubuntu-24.04-arm-16 - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: .github/workflows/containers/github-action-ci/ - # podman is not installed by default on the ARM64 images. - - name: Install Podman - if: runner.arch == 'ARM64' - run: | - sudo apt-get install podman - - name: Write Variables - id: vars - run: | - tag=$(git rev-parse --short=12 HEAD) - container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/${{ matrix.arch }}/ci-ubuntu-24.04" - echo "container-name=$container_name" >> $GITHUB_OUTPUT - echo "container-name-agent=$container_name-agent" >> $GITHUB_OUTPUT - echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT - echo "container-name-agent-tag=$container_name-agent:$tag" >> $GITHUB_OUTPUT - echo "container-filename=$(echo $container_name:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT - echo "container-agent-filename=$(echo $container_name-agent:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT - - name: Build container - working-directory: ./.github/workflows/containers/github-action-ci/ - run: | - podman build --target ci-container -t ${{ steps.vars.outputs.container-name-tag }} . - podman build --target ci-container-agent -t ${{ steps.vars.outputs.container-name-agent-tag }} . - - # Save the container so we have it in case the push fails. This also - # allows us to separate the push step into a different job so we can - # maintain minimal permissions while building the container. - - name: Save container image - run: | - podman save ${{ steps.vars.outputs.container-name-tag }} > ${{ steps.vars.outputs.container-filename }} - podman save ${{ steps.vars.outputs.container-name-agent-tag }} > ${{ steps.vars.outputs.container-agent-filename }} - - - name: Upload container image - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: container-${{ matrix.arch }} - path: "*.tar" - retention-days: 14 - - - name: Test Container - run: | - for image in ${{ steps.vars.outputs.container-name-tag }}; do - # Use --pull=never to ensure we are testing the just built image. - podman run --pull=never --rm -it $image /usr/bin/bash -x -c 'cd $HOME && printf '\''#include \nint main(int argc, char **argv) { std::cout << "Hello\\n"; }'\'' | clang++ -x c++ - && ./a.out | grep Hello' - done - - push-ci-container: - if: github.event_name == 'push' - needs: - - build-ci-container - permissions: - packages: write - runs-on: ubuntu-24.04 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Download container - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - - - name: Push Container - run: | - function push_container { - image_name=$1 - latest_name=$(echo $image_name | sed 's/:[a-f0-9]\+$/:latest/g') - podman tag $image_name $latest_name - echo "Pushing $image_name ..." - podman push $image_name - echo "Pushing $latest_name ..." - podman push $latest_name - } - - podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io - for f in $(find . -iname *.tar); do - image_name=$(podman load -q -i $f | sed 's/Loaded image: //g') - push_container $image_name - - if echo $image_name | grep '/amd64/'; then - # For amd64, create an alias with the arch component removed. - # This matches the convention used on dockerhub. - default_image_name=$(echo $(dirname $(dirname $image_name))/$(basename $image_name)) - podman tag $image_name $default_image_name - push_container $default_image_name - fi - done diff --git a/.github/workflows/build-metrics-container.yml b/.github/workflows/build-metrics-container.yml deleted file mode 100644 index af4d599f76417..0000000000000 --- a/.github/workflows/build-metrics-container.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Build Metrics Container - -permissions: - contents: read - -on: - push: - branches: - - main - paths: - - .github/workflows/build-metrics-container.yml - - '.ci/metrics/**' - pull_request: - branches: - - main - paths: - - .github/workflows/build-metrics-container.yml - - '.ci/metrics/**' - -jobs: - build-metrics-container: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - outputs: - container-name: ${{ steps.vars.outputs.container-name }} - container-name-tag: ${{ steps.vars.outputs.container-name-tag }} - container-filename: ${{ steps.vars.outputs.container-filename }} - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: .ci/metrics/ - - name: Write Variables - id: vars - run: | - tag=`date +%s` - container_name="ghcr.io/$GITHUB_REPOSITORY_OWNER/metrics" - echo "container-name=$container_name" >> $GITHUB_OUTPUT - echo "container-name-tag=$container_name:$tag" >> $GITHUB_OUTPUT - echo "container-filename=$(echo $container_name:$tag | sed -e 's/\//-/g' -e 's/:/-/g').tar" >> $GITHUB_OUTPUT - - name: Build Container - working-directory: ./.ci/metrics - run: | - podman build -t ${{ steps.vars.outputs.container-name-tag }} -f Dockerfile . - # Save the container so we have it in case the push fails. This also - # allows us to separate the push step into a different job so we can - # maintain minimal permissions while building the container. - - name: Save Container Image - run: | - podman save ${{ steps.vars.outputs.container-name-tag }} > ${{ steps.vars.outputs.container-filename }} - - name: Upload Container Image - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: container - path: ${{ steps.vars.outputs.container-filename }} - retention-days: 14 - - push-metrics-container: - if: github.event_name == 'push' - needs: - - build-metrics-container - permissions: - packages: write - runs-on: ubuntu-24.04 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Download Container - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: container - - name: Push Container - run: | - podman load -i ${{ needs.build-metrics-container.outputs.container-filename }} - podman tag ${{ needs.build-metrics-container.outputs.container-name-tag }} ${{ needs.build-metrics-container.outputs.container-name }}:latest - podman login -u ${{ github.actor }} -p $GITHUB_TOKEN ghcr.io - podman push ${{ needs.build-metrics-container.outputs.container-name-tag }} - podman push ${{ needs.build-metrics-container.outputs.container-name }}:latest diff --git a/.github/workflows/ci-post-commit-analyzer-run.py b/.github/workflows/ci-post-commit-analyzer-run.py deleted file mode 100644 index e5f52d3b2fa67..0000000000000 --- a/.github/workflows/ci-post-commit-analyzer-run.py +++ /dev/null @@ -1,34 +0,0 @@ -import json -import multiprocessing -import os -import re -import subprocess -import sys - - -def run_analyzer(data): - os.chdir(data["directory"]) - command = ( - data["command"] - + f" --analyze --analyzer-output html -o analyzer-results -Xclang -analyzer-config -Xclang max-nodes=75000" - ) - print(command) - subprocess.run(command, shell=True, check=True) - - -def pool_error(e): - print("Error analyzing file:", e) - - -def main(): - db_path = sys.argv[1] - database = json.load(open(db_path)) - - with multiprocessing.Pool() as pool: - pool.map_async(run_analyzer, [k for k in database], error_callback=pool_error) - pool.close() - pool.join() - - -if __name__ == "__main__": - main() diff --git a/.github/workflows/ci-post-commit-analyzer.yml b/.github/workflows/ci-post-commit-analyzer.yml deleted file mode 100644 index b8074859d23a2..0000000000000 --- a/.github/workflows/ci-post-commit-analyzer.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Post-Commit Static Analyzer - -permissions: - contents: read - -on: - push: - branches: - - 'release/**' - paths: - - 'clang/**' - - 'llvm/**' - - '.github/workflows/ci-post-commit-analyzer.yml' - pull_request: - types: - - opened - - synchronize - - reopened - - closed - paths: - - '.github/workflows/ci-post-commit-analyzer.yml' - - '.github/workflows/ci-post-commit-analyzer-run.py' - schedule: - - cron: '30 0 * * *' - -concurrency: - group: >- - llvm-project-${{ github.workflow }}-${{ github.event_name == 'pull_request' && - ( github.event.pull_request.number || github.ref) }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - post-commit-analyzer: - if: >- - github.repository_owner == 'llvm' && - github.event.action != 'closed' - runs-on: ubuntu-24.04 - container: - image: 'ghcr.io/llvm/ci-ubuntu-24.04:latest' - env: - LLVM_VERSION: 18 - steps: - - name: Checkout Source - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - # A full build of llvm, clang, lld, and lldb takes about 250MB - # of ccache space. There's not much reason to have more than this, - # because we usually won't need to save cache entries from older - # builds. Also, there is an overall 10GB cache limit, and each - # run creates a new cache entry so we want to ensure that we have - # enough cache space for all the tests to run at once and still - # fit under the 10 GB limit. - # Default to 2G to workaround: https://github.com/hendrikmuhs/ccache-action/issues/174 - max-size: 2G - key: post-commit-analyzer - variant: sccache - - - name: Configure - run: | - cmake -B build -S llvm -G Ninja \ - -DLLVM_ENABLE_ASSERTIONS=ON \ - -DLLVM_ENABLE_PROJECTS=clang \ - -DLLVM_BUILD_LLVM_DYLIB=ON \ - -DLLVM_LINK_LLVM_DYLIB=ON \ - -DCMAKE_CXX_COMPILER=clang++ \ - -DCMAKE_C_COMPILER=clang \ - -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ - -DCMAKE_C_COMPILER_LAUNCHER=sccache \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DLLVM_INCLUDE_TESTS=OFF \ - -DCLANG_INCLUDE_TESTS=OFF \ - -DCMAKE_BUILD_TYPE=Release - - - name: Build - run: | - # FIXME: We need to build all the generated header files in order to be able to run - # the analyzer on every file. Building libLLVM and libclang is probably overkill for - # this, but it's better than building every target. - ninja -v -C build libLLVM.so libclang.so - - # Run the analyzer. - python3 .github/workflows/ci-post-commit-analyzer-run.py build/compile_commands.json - - scan-build --generate-index-only build/analyzer-results - - - name: Upload Results - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - if: always() - with: - name: analyzer-results - path: 'build/analyzer-results/*' - diff --git a/.github/workflows/commit-access-greeter.yml b/.github/workflows/commit-access-greeter.yml deleted file mode 100644 index a5fbbbb94e222..0000000000000 --- a/.github/workflows/commit-access-greeter.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Commit Access Greeter - -on: - issues: - types: - - labeled - -permissions: - contents: read - -jobs: - commit-access-greeter: - permissions: - issues: write - pull-requests: read - if: >- - github.repository_owner == 'llvm' && - github.event.label.name == 'infra:commit-access-request' - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - with: - sparse-checkout: llvm/utils/git/ - - - name: Setup Automation Script - working-directory: ./llvm/utils/git/ - run: | - pip install --require-hashes -r requirements.txt - - - name: Add comments to issue - working-directory: ./llvm/utils/git/ - env: - LABEL_NAME: ${{ github.event.label.name }} - GITHUB_TOKEN: ${{ github.token }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - run: | - python3 ./github-automation.py \ - --token $GITHUB_TOKEN \ - commit-request-greeter \ - --issue-number $ISSUE_NUMBER diff --git a/.github/workflows/commit-access-review.py b/.github/workflows/commit-access-review.py deleted file mode 100644 index 4f539fe98004a..0000000000000 --- a/.github/workflows/commit-access-review.py +++ /dev/null @@ -1,402 +0,0 @@ -#!/usr/bin/env python3 -# ===-- commit-access-review.py --------------------------------------------===# -# -# 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 -# -# ===------------------------------------------------------------------------===# -# -# ===------------------------------------------------------------------------===# - -import datetime -import github -import re -import requests -import time -import sys -import re - - -class User: - THRESHOLD = 5 - - def __init__(self, name, triage_list): - self.name = name - self.authored = 0 - self.merged = 0 - self.reviewed = 0 - self.triage_list = triage_list - - def add_authored(self, val=1): - self.authored += val - if self.meets_threshold(): - print(self.name, "meets the threshold with authored commits") - del self.triage_list[self.name] - - def set_authored(self, val): - self.authored = 0 - self.add_authored(val) - - def add_merged(self, val=1): - self.merged += val - if self.meets_threshold(): - print(self.name, "meets the threshold with merged commits") - del self.triage_list[self.name] - - def add_reviewed(self, val=1): - self.reviewed += val - if self.meets_threshold(): - print(self.name, "meets the threshold with reviewed commits") - del self.triage_list[self.name] - - def get_total(self): - return self.authored + self.merged + self.reviewed - - def meets_threshold(self): - return self.get_total() >= self.THRESHOLD - - def __repr__(self): - return "{} : a: {} m: {} r: {}".format( - self.name, self.authored, self.merged, self.reviewed - ) - - -def check_manual_requests( - gh: github.Github, start_date: datetime.datetime -) -> list[str]: - """ - Return a list of users who have been asked since ``start_date`` if they - want to keep their commit access or if they have applied for commit - access since ``start_date`` - """ - - query = """ - query ($query: String!, $after: String) { - search(query: $query, type: ISSUE, first: 100, after: $after) { - nodes { - ... on Issue { - author { - login - } - body - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - """ - formatted_start_date = start_date.strftime("%Y-%m-%dT%H:%M:%S") - variables = { - "query": f"type:issue created:>{formatted_start_date} org:llvm repo:llvm-project label:infra:commit-access,infra:commit-access-request" - } - - has_next_page = True - users = [] - while has_next_page: - res_header, res_data = gh._Github__requester.graphql_query( - query=query, variables=variables - ) - data = res_data["data"] - for issue in data["search"]["nodes"]: - users.extend([user[1:] for user in re.findall("@[^ ,\n]+", issue["body"])]) - if issue["author"]: - users.append(issue["author"]["login"]) - has_next_page = data["search"]["pageInfo"]["hasNextPage"] - if has_next_page: - variables["after"] = data["search"]["pageInfo"]["endCursor"] - return users - - -def get_num_commits(gh: github.Github, user: str, start_date: datetime.datetime) -> int: - """ - Get number of commits that ``user`` has been made since ``start_date`. - """ - variables = { - "owner": "llvm", - "user": user, - "start_date": start_date.strftime("%Y-%m-%dT%H:%M:%S"), - } - - user_query = """ - query ($user: String!) { - user(login: $user) { - id - } - } - """ - - res_header, res_data = gh._Github__requester.graphql_query( - query=user_query, variables=variables - ) - data = res_data["data"] - variables["user_id"] = data["user"]["id"] - - query = """ - query ($owner: String!, $user_id: ID!, $start_date: GitTimestamp!){ - organization(login: $owner) { - teams(query: "llvm-committers" first:1) { - nodes { - repositories { - nodes { - ref(qualifiedName: "main") { - target { - ... on Commit { - history(since: $start_date, author: {id: $user_id }) { - totalCount - } - } - } - } - } - } - } - } - } - } - """ - count = 0 - res_header, res_data = gh._Github__requester.graphql_query( - query=query, variables=variables - ) - data = res_data["data"] - for repo in data["organization"]["teams"]["nodes"][0]["repositories"]["nodes"]: - count += int(repo["ref"]["target"]["history"]["totalCount"]) - if count >= User.THRESHOLD: - break - return count - - -def is_new_committer_query_repo( - gh: github.Github, user: str, start_date: datetime.datetime -) -> bool: - """ - Determine if ``user`` is a new committer. A new committer can keep their - commit access even if they don't meet the criteria. - """ - variables = { - "user": user, - } - - user_query = """ - query ($user: String!) { - user(login: $user) { - id - } - } - """ - - res_header, res_data = gh._Github__requester.graphql_query( - query=user_query, variables=variables - ) - data = res_data["data"] - variables["owner"] = "llvm" - variables["user_id"] = data["user"]["id"] - variables["start_date"] = start_date.strftime("%Y-%m-%dT%H:%M:%S") - - query = """ - query ($owner: String!, $user_id: ID!){ - organization(login: $owner) { - repository(name: "llvm-project") { - ref(qualifiedName: "main") { - target { - ... on Commit { - history(author: {id: $user_id }, first: 5) { - nodes { - committedDate - } - } - } - } - } - } - } - } - """ - - res_header, res_data = gh._Github__requester.graphql_query( - query=query, variables=variables - ) - data = res_data["data"] - repo = data["organization"]["repository"] - commits = repo["ref"]["target"]["history"]["nodes"] - if len(commits) == 0: - return True - committed_date = commits[-1]["committedDate"] - if datetime.datetime.strptime(committed_date, "%Y-%m-%dT%H:%M:%SZ") < start_date: - return False - return True - - -def is_new_committer( - gh: github.Github, user: str, start_date: datetime.datetime -) -> bool: - """ - Wrapper around is_new_commiter_query_repo to handle exceptions. - """ - try: - return is_new_committer_query_repo(gh, user, start_date) - except: - pass - return True - - -def get_review_count( - gh: github.Github, user: str, start_date: datetime.datetime -) -> int: - """ - Return the number of reviews that ``user`` has done since ``start_date``. - """ - query = """ - query ($query: String!) { - search(query: $query, type: ISSUE, first: 5) { - issueCount - } - } - """ - formatted_start_date = start_date.strftime("%Y-%m-%dT%H:%M:%S") - variables = { - "owner": "llvm", - "repo": "llvm-project", - "user": user, - "query": f"type:pr commenter:{user} -author:{user} merged:>{formatted_start_date} org:llvm", - } - - res_header, res_data = gh._Github__requester.graphql_query( - query=query, variables=variables - ) - data = res_data["data"] - return int(data["search"]["issueCount"]) - - -def count_prs(gh: github.Github, triage_list: dict, start_date: datetime.datetime): - """ - Fetch all the merged PRs for the project since ``start_date`` and update - ``triage_list`` with the number of PRs merged for each user. - """ - - query = """ - query ($query: String!, $after: String) { - search(query: $query, type: ISSUE, first: 100, after: $after) { - issueCount, - nodes { - ... on PullRequest { - author { - login - } - mergedBy { - login - } - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - """ - date_begin = start_date - date_end = None - while date_begin < datetime.datetime.now(): - date_end = date_begin + datetime.timedelta(days=7) - formatted_date_begin = date_begin.strftime("%Y-%m-%dT%H:%M:%S") - formatted_date_end = date_end.strftime("%Y-%m-%dT%H:%M:%S") - variables = { - "query": f"type:pr is:merged merged:{formatted_date_begin}..{formatted_date_end} org:llvm", - } - has_next_page = True - while has_next_page: - print(variables) - res_header, res_data = gh._Github__requester.graphql_query( - query=query, variables=variables - ) - data = res_data["data"] - for pr in data["search"]["nodes"]: - # Users can be None if the user has been deleted. - if not pr["author"]: - continue - author = pr["author"]["login"] - if author in triage_list: - triage_list[author].add_authored() - - if not pr["mergedBy"]: - continue - merger = pr["mergedBy"]["login"] - if author == merger: - continue - if merger not in triage_list: - continue - triage_list[merger].add_merged() - - has_next_page = data["search"]["pageInfo"]["hasNextPage"] - if has_next_page: - variables["after"] = data["search"]["pageInfo"]["endCursor"] - date_begin = date_end - - -def main(): - token = sys.argv[1] - gh = github.Github(login_or_token=token) - org = gh.get_organization("llvm") - repo = org.get_repo("llvm-project") - one_year_ago = datetime.datetime.now() - datetime.timedelta(days=365) - triage_list = {} - for collaborator in repo.get_collaborators(permission="push"): - triage_list[collaborator.login] = User(collaborator.login, triage_list) - - print("Start:", len(triage_list), "triagers") - # Step 0 Check if users have requested commit access in the last year. - for user in check_manual_requests(gh, one_year_ago): - if user in triage_list: - print(user, "requested commit access in the last year.") - del triage_list[user] - print("After Request Check:", len(triage_list), "triagers") - - # Step 1 count all PRs authored or merged - count_prs(gh, triage_list, one_year_ago) - - print("After PRs:", len(triage_list), "triagers") - - if len(triage_list) == 0: - sys.exit(0) - - # Step 2 check for reviews - for user in list(triage_list.keys()): - review_count = get_review_count(gh, user, one_year_ago) - triage_list[user].add_reviewed(review_count) - - print("After Reviews:", len(triage_list), "triagers") - - if len(triage_list) == 0: - sys.exit(0) - - # Step 3 check for number of commits - for user in list(triage_list.keys()): - num_commits = get_num_commits(gh, user, one_year_ago) - # Override the total number of commits to not double count commits and - # authored PRs. - triage_list[user].set_authored(num_commits) - - print("After Commits:", len(triage_list), "triagers") - - # Step 4 check for new committers - for user in list(triage_list.keys()): - print("Checking", user) - if is_new_committer(gh, user, one_year_ago): - print("Removing new committer: ", user) - del triage_list[user] - - print("Complete:", len(triage_list), "triagers") - - with open("triagers.log", "w") as triagers_log: - for user in triage_list: - print(triage_list[user].__repr__()) - triagers_log.write(user + "\n") - - -if __name__ == "__main__": - main() diff --git a/.github/workflows/commit-access-review.yml b/.github/workflows/commit-access-review.yml deleted file mode 100644 index d401a137737c4..0000000000000 --- a/.github/workflows/commit-access-review.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Commit Access Review - -on: - workflow_dispatch: - schedule: - # * is a special character in YAML so you have to quote this string - - cron: '0 7 1 * *' - -permissions: - contents: read - -jobs: - commit-access-review: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Install dependencies - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - - - name: Run Script - env: - GITHUB_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - run: | - python3 .github/workflows/commit-access-review.py $GITHUB_TOKEN - - - name: Upload Triage List - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - with: - name: triagers - path: triagers.log diff --git a/.github/workflows/containers/github-action-ci-windows/Dockerfile b/.github/workflows/containers/github-action-ci-windows/Dockerfile deleted file mode 100644 index b909d14b4eeeb..0000000000000 --- a/.github/workflows/containers/github-action-ci-windows/Dockerfile +++ /dev/null @@ -1,100 +0,0 @@ -# Agent image for LLVM org cluster. -# .net 4.8 is required by chocolately package manager. -FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2022 - -# Restore the default Windows shell for correct batch processing. -SHELL ["cmd", "/S", "/C"] - -# Download the Build Tools bootstrapper. -ADD https://aka.ms/vs/16/release/vs_buildtools.exe /TEMP/vs_buildtools.exe - -RUN powershell -Command Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) - -# Download channel for fixed install. -ARG CHANNEL_URL=https://aka.ms/vs/16/release/channel -ADD ${CHANNEL_URL} /TEMP/VisualStudio.chman - -# Install Build Tools with C++ workload. -# - Documentation for docker installation -# https://docs.microsoft.com/en-us/visualstudio/install/build-tools-container?view=vs-2019 -# - Documentation on workloads -# https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools?view=vs-2019#c-build-tools -# - Documentation on flags -# https://docs.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio?view=vs-2019 -RUN /TEMP/vs_buildtools.exe --quiet --wait --norestart --nocache \ - --channelUri C:\TEMP\VisualStudio.chman \ - --installChannelUri C:\TEMP\VisualStudio.chman \ - --installPath C:\BuildTools \ - --add Microsoft.VisualStudio.Workload.VCTools \ - --add Microsoft.VisualStudio.Component.VC.ATL \ - --includeRecommended \ - || IF "%ERRORLEVEL%"=="3010" EXIT 0 - -# Register DIA dll (Debug Interface Access) so it can be used to symbolize -# the stack traces. Register dll for 32 and 64 bit. -# see https://developercommunity.visualstudio.com/content/problem/290674/msdia140dll-is-not-registered-on-vs2017-hosts.html - -RUN regsvr32 /S "C:\BuildTools\DIA SDK\bin\amd64\msdia140.dll" & \ - regsvr32 /S "C:\BuildTools\DIA SDK\bin\msdia140.dll" - -# install tools as described in https://llvm.org/docs/GettingStartedVS.html -# and a few more that were not documented... -# Pin an older version of Python; the current Python 3.10 fails when -# doing "pip install" for the other dependencies, as it fails to find libxml -# while compiling some package. -# We version pin the other packages as well to ensure the container build is as -# reproducible as possible to prevent issues when upgrading only part of the -# container. -RUN choco install -y ninja --version 1.13.1 && \ - choco install -y git --version 2.50.1 && \ - choco install -y sccache --version 0.10.0 && \ - choco install -y python3 --version 3.9.7 - -# Testing requires psutil -RUN pip install psutil - -# configure Python encoding -ENV PYTHONIOENCODING=UTF-8 - -# update the path variable -# C:\Program Files\Git\usr\bin contains a usable bash and other unix tools. -# C:\llvm-mingw\bin contains Clang configured for mingw targets and -# corresponding sysroots. Both the 'llvm' package (with Clang defaulting -# to MSVC targets) and this directory contains executables named -# 'clang.exe' - add this last to let the other one have precedence. -# To use these compilers, use the triple prefixed form, e.g. -# x86_64-w64-mingw32-clang. -# C:\buildtools and SDK paths are ones that are set by c:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 -host_arch=amd64 -RUN powershell -Command \ - [System.Environment]::SetEnvironmentVariable('PATH', \ - [System.Environment]::GetEnvironmentVariable('PATH', 'machine') + ';C:\Program Files\Git\usr\bin;C:\llvm-mingw\bin' \ - + ';C:\BuildTools\Common7\IDE\' \ - + ';C:\BuildTools\Common7\IDE\CommonExt ensions\Microsoft\TeamFoundation\Team Explorer' \ - + ';C:\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin' \ - + ';C:\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja' \ - + ';C:\BuildTools\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer' \ - + ';C:\BuildTools\Common7\IDE\CommonExtensions\Microsoft\TestWindow' \ - + ';C:\BuildTools\Common7\IDE\VC\VCPackages' \ - + ';C:\BuildTools\Common7\Tools\' \ - + ';C:\BuildTools\Common7\Tools\devinit' \ - + ';C:\BuildTools\MSBuild\Current\Bin' \ - + ';C:\BuildTools\MSBuild\Current\bin\Roslyn' \ - + ';C:\BuildTools\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64' \ - + ';C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\' \ - + ';C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64' \ - + ';C:\Program Files (x86)\Windows Kits\10\bin\x64' \ - + ';C:\Windows\Microsoft.NET\Framework64\v4.0.30319' \ - ,'machine') - -# support long file names during git checkout -RUN git config --system core.longpaths true & \ - git config --global core.autocrlf false - -ARG RUNNER_VERSION=2.326.0 -ENV RUNNER_VERSION=$RUNNER_VERSION - -RUN powershell -Command \ - Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v${env:RUNNER_VERSION}/actions-runner-win-x64-${env:RUNNER_VERSION}.zip -OutFile actions-runner-win.zip ; \ - Add-Type -AssemblyName System.IO.Compression.FileSystem ; \ - [System.IO.Compression.ZipFile]::ExtractToDirectory('actions-runner-win.zip', $PWD) ;\ - rm actions-runner-win.zip diff --git a/.github/workflows/containers/github-action-ci/Dockerfile b/.github/workflows/containers/github-action-ci/Dockerfile deleted file mode 100644 index efe08ebc221c5..0000000000000 --- a/.github/workflows/containers/github-action-ci/Dockerfile +++ /dev/null @@ -1,96 +0,0 @@ -FROM docker.io/library/ubuntu:24.04 as base -ENV LLVM_SYSROOT=/opt/llvm - -FROM base as stage1-toolchain -ENV LLVM_VERSION=20.1.8 - -RUN apt-get update && \ - apt-get install -y \ - wget \ - gcc \ - g++ \ - cmake \ - ninja-build \ - python3 \ - git \ - curl \ - zlib1g-dev && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN curl -O -L https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-$LLVM_VERSION.tar.gz && \ - tar -xf llvmorg-$LLVM_VERSION.tar.gz && \ - rm -f llvmorg-$LLVM_VERSION.tar.gz - -WORKDIR /llvm-project-llvmorg-$LLVM_VERSION - -RUN cmake -B ./build -G Ninja ./llvm \ - -C ./clang/cmake/caches/BOLT-PGO.cmake \ - -DBOOTSTRAP_LLVM_ENABLE_LLD=ON \ - -DBOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD=ON \ - -DPGO_INSTRUMENT_LTO=Thin \ - -DLLVM_ENABLE_RUNTIMES="compiler-rt" \ - -DCMAKE_INSTALL_PREFIX="$LLVM_SYSROOT" \ - -DLLVM_ENABLE_PROJECTS="bolt;clang;lld;clang-tools-extra" \ - -DLLVM_DISTRIBUTION_COMPONENTS="lld;compiler-rt;clang-format;scan-build;llvm-symbolizer" \ - -DCLANG_DEFAULT_LINKER="lld" - -RUN ninja -C ./build stage2-clang-bolt stage2-install-distribution && ninja -C ./build install-distribution - -FROM base as ci-container - -COPY --from=stage1-toolchain $LLVM_SYSROOT $LLVM_SYSROOT - -# Need to install curl for hendrikmuhs/ccache-action -# Need nodejs for some of the GitHub actions. -# Need perl-modules for clang analyzer tests. -# Need git for SPIRV-Tools tests. -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y \ - binutils \ - cmake \ - curl \ - git \ - libstdc++-11-dev \ - ninja-build \ - nodejs \ - perl-modules \ - python3-psutil \ - sudo \ - # These are needed by the premerge pipeline. Pip is used to install - # dependent python packages and ccache is used for build caching. File and - # tzdata are used for tests. - python3-pip \ - ccache \ - file \ - tzdata \ - sccache && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -ENV LLVM_SYSROOT=$LLVM_SYSROOT -ENV PATH=${LLVM_SYSROOT}/bin:${PATH} - -# Create a new user to avoid test failures related to a lack of expected -# permissions issues in some tests. Set the user id to 1001 as that is the -# user id that Github Actions uses to perform the checkout action. -RUN useradd gha -u 1001 -m -s /bin/bash - -# Also add the user to passwordless sudoers so that we can install software -# later on without having to rebuild the container. -RUN adduser gha sudo -RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers - -USER gha -WORKDIR /home/gha - -FROM ci-container as ci-container-agent - -ENV GITHUB_RUNNER_VERSION=2.326.0 - -RUN mkdir actions-runner && \ - cd actions-runner && \ - curl -O -L https://github.com/actions/runner/releases/download/v$GITHUB_RUNNER_VERSION/actions-runner-linux-x64-$GITHUB_RUNNER_VERSION.tar.gz && \ - tar xzf ./actions-runner-linux-x64-$GITHUB_RUNNER_VERSION.tar.gz && \ - rm ./actions-runner-linux-x64-$GITHUB_RUNNER_VERSION.tar.gz - diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 3970271e4adbd..0000000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,215 +0,0 @@ -# LLVM Documentation CI -# 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 - -name: "Test documentation build" - -permissions: - contents: read - -on: - push: - branches: - - 'main' - paths: - - 'llvm/docs/**' - - 'clang/docs/**' - - 'clang/include/clang/Basic/AttrDocs.td' - - 'clang/include/clang/Driver/ClangOptionDocs.td' - - 'clang/include/clang/Basic/DiagnosticDocs.td' - - 'clang-tools-extra/docs/**' - - 'lldb/docs/**' - - 'libunwind/docs/**' - - 'libcxx/docs/**' - - 'libc/docs/**' - - 'lld/docs/**' - - 'openmp/docs/**' - - 'polly/docs/**' - - 'flang/docs/**' - - 'flang/include/flang/Optimizer/Dialect/FIROps.td' - - '.github/workflows/docs.yml' - pull_request: - paths: - - 'llvm/docs/**' - - 'clang/docs/**' - - 'clang/include/clang/Basic/AttrDocs.td' - - 'clang/include/clang/Driver/ClangOptionDocs.td' - - 'clang/include/clang/Basic/DiagnosticDocs.td' - - 'clang-tools-extra/docs/**' - - 'lldb/docs/**' - - 'libunwind/docs/**' - - 'libcxx/docs/**' - - 'libc/docs/**' - - 'lld/docs/**' - - 'openmp/docs/**' - - 'polly/docs/**' - - 'flang/docs/**' - - 'flang/include/flang/Optimizer/Dialect/FIROps.td' - - '.github/workflows/docs.yml' - -jobs: - check-docs-build: - name: "Test documentation build" - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 2 - - name: Get subprojects that have doc changes - id: docs-changed-subprojects - uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1 - with: - skip_initial_fetch: true - base_sha: 'HEAD~1' - sha: 'HEAD' - files_yaml: | - llvm: - - 'llvm/docs/**' - clang: - - 'clang/docs/**' - - 'clang/include/clang/Basic/AttrDocs.td' - - 'clang/include/clang/Driver/ClangOptionDocs.td' - - 'clang/include/clang/Basic/DiagnosticDocs.td' - clang-tools-extra: - - 'clang-tools-extra/docs/**' - lldb: - - 'lldb/docs/**' - libunwind: - - 'libunwind/docs/**' - libcxx: - - 'libcxx/docs/**' - libc: - - 'libc/docs/**' - lld: - - 'lld/docs/**' - openmp: - - 'openmp/docs/**' - polly: - - 'polly/docs/**' - flang: - - 'flang/docs/**' - - 'flang/include/flang/Optimizer/Dialect/FIROps.td' - workflow: - - '.github/workflows/docs.yml' - - name: Setup Python env - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 - with: - python-version: '3.11' - cache: 'pip' - cache-dependency-path: 'llvm/docs/requirements-hashed.txt' - - name: Install python dependencies - run: pip install -r llvm/docs/requirements-hashed.txt - - name: Install system dependencies - run: | - sudo apt-get update - # swig and graphviz are lldb specific dependencies - sudo apt-get install -y cmake ninja-build swig graphviz - - name: Setup output folder - run: mkdir built-docs - - name: Build LLVM docs - if: | - steps.docs-changed-subprojects.outputs.llvm_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B llvm-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C llvm-build docs-llvm-html docs-llvm-man - mkdir built-docs/llvm - cp -r llvm-build/docs/* built-docs/llvm/ - - name: Build Clang docs - if: | - steps.docs-changed-subprojects.outputs.clang_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B clang-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C clang-build docs-clang-html docs-clang-man - mkdir built-docs/clang - cp -r clang-build/docs/* built-docs/clang/ - - name: Build clang-tools-extra docs - if: | - steps.docs-changed-subprojects.outputs.clang-tools-extra_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B clang-tools-extra-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C clang-tools-extra-build docs-clang-tools-html docs-clang-tools-man - mkdir built-docs/clang-tools-extra - cp -r clang-tools-extra-build/docs/* built-docs/clang-tools-extra/ - - name: Build LLDB docs - if: | - steps.docs-changed-subprojects.outputs.lldb_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B lldb-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C lldb-build docs-lldb-html docs-lldb-man - mkdir built-docs/lldb - cp -r lldb-build/docs/* built-docs/lldb/ - - name: Build libunwind docs - if: | - steps.docs-changed-subprojects.outputs.libunwind_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B libunwind-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES="libunwind" -DLLVM_ENABLE_SPHINX=ON ./runtimes - TZ=UTC ninja -C libunwind-build docs-libunwind-html - mkdir built-docs/libunwind - cp -r libunwind-build/libunwind/docs/* built-docs/libunwind - - name: Build libcxx docs - if: | - steps.docs-changed-subprojects.outputs.libcxx_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B libcxx-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES="libcxxabi;libcxx;libunwind" -DLLVM_ENABLE_SPHINX=ON ./runtimes - TZ=UTC ninja -C libcxx-build docs-libcxx-html - mkdir built-docs/libcxx - cp -r libcxx-build/libcxx/docs/* built-docs/libcxx/ - - name: Build libc docs - if: | - steps.docs-changed-subprojects.outputs.libc_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B libc-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RUNTIMES="libc" -DLLVM_ENABLE_SPHINX=ON ./runtimes - TZ=UTC ninja -C libc-build docs-libc-html - mkdir built-docs/libc - cp -r libc-build/libc/docs/* built-docs/libc/ - - name: Build LLD docs - if: | - steps.docs-changed-subprojects.outputs.lld_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B lld-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="lld" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C lld-build docs-lld-html - mkdir built-docs/lld - cp -r lld-build/docs/* built-docs/lld/ - - name: Build OpenMP docs - if: | - steps.docs-changed-subprojects.outputs.openmp_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B openmp-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;openmp" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C openmp-build docs-openmp-html - mkdir built-docs/openmp - cp -r openmp-build/docs/* built-docs/openmp/ - - name: Build Polly docs - if: | - steps.docs-changed-subprojects.outputs.polly_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B polly-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="polly" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C polly-build docs-polly-html docs-polly-man - mkdir built-docs/polly - cp -r polly-build/docs/* built-docs/polly/ - - name: Build Flang docs - if: | - steps.docs-changed-subprojects.outputs.flang_any_changed == 'true' || - steps.docs-changed-subprojects.outputs.workflow_any_changed == 'true' - run: | - cmake -B flang-build -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;mlir;flang" -DLLVM_ENABLE_SPHINX=ON ./llvm - TZ=UTC ninja -C flang-build docs-flang-html docs-flang-man - mkdir built-docs/flang - cp -r flang-build/docs/* built-docs/flang/ - - name: Upload docs - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: docs-output - path: built-docs/ diff --git a/.github/workflows/email-check.yaml b/.github/workflows/email-check.yaml deleted file mode 100644 index 904ad718f97dd..0000000000000 --- a/.github/workflows/email-check.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: "Check for private emails used in PRs" - -on: - pull_request: - types: - - opened - -permissions: - contents: read - -jobs: - validate_email: - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Extract author email - id: author - run: | - git log -1 - echo "EMAIL=$(git show -s --format='%ae' HEAD~0)" >> $GITHUB_OUTPUT - # Create empty comment file - echo "[]" > comments - - - name: Validate author email - if: ${{ endsWith(steps.author.outputs.EMAIL, 'noreply.github.com') }} - env: - COMMENT: >- - ⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
- Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
- See [LLVM Developer Policy](https://llvm.org/docs/DeveloperPolicy.html#email-addresses) and - [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. - run: | - cat << EOF > comments - [{"body" : "$COMMENT"}] - EOF - - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - if: always() - with: - name: workflow-args - path: | - comments diff --git a/.github/workflows/get-llvm-version/action.yml b/.github/workflows/get-llvm-version/action.yml deleted file mode 100644 index 2218d926fc13d..0000000000000 --- a/.github/workflows/get-llvm-version/action.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Get LLVM Version -description: >- - Get the LLVM version from the llvm-project source tree. This action assumes - the llvm-project sources have already been checked out into GITHUB_WORKSPACE. - -outputs: - major: - description: LLVM major version - value: ${{ steps.version.outputs.major }} - minor: - description: LLVM minor version - value: ${{ steps.version.outputs.minor }} - patch: - description: LLVM patch version - value: ${{ steps.version.outputs.patch }} - -runs: - using: "composite" - steps: - - name: Get Version - shell: bash - id: version - run: | - for v in major minor patch; do - echo "$v=`llvm/utils/release/get-llvm-version.sh --$v`" >> $GITHUB_OUTPUT - done diff --git a/.github/workflows/gha-codeql.yml b/.github/workflows/gha-codeql.yml new file mode 100644 index 0000000000000..622ef326cb96d --- /dev/null +++ b/.github/workflows/gha-codeql.yml @@ -0,0 +1,37 @@ +name: Github Actions CodeQL + +permissions: + contents: read + +on: + pull_request: + branches: + - npu/main + paths: + - '.github/**' + schedule: + - cron: '30 0 * * *' + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + codeql: + name: 'Github Actions CodeQL' + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Checkout LLVM + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + sparse-checkout: | + .github/ + - name: Initialize CodeQL + uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 + with: + languages: actions + queries: security-extended + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 diff --git a/.github/workflows/hlsl-matrix.yaml b/.github/workflows/hlsl-matrix.yaml deleted file mode 100644 index c63a32acd2b3e..0000000000000 --- a/.github/workflows/hlsl-matrix.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: HLSL Tests - -permissions: - contents: read - -on: - workflow_dispatch: - pull_request: - branches: - - main - paths: - - llvm/**/DirectX/** - - .github/workflows/hlsl* - - clang/*HLSL*/**/* - - clang/**/*HLSL* - - llvm/**/Frontend/HLSL/**/* - -jobs: - HLSL-Tests: - strategy: - fail-fast: false - matrix: - runs-on: - - hlsl-macos - - uses: ./.github/workflows/hlsl-test-all.yaml - with: - SKU: hlsl-macos - TestTarget: check-hlsl-clang-mtl # TODO: This target changes based on SKU - LLVM-ref: ${{ github.ref }} diff --git a/.github/workflows/hlsl-test-all.yaml b/.github/workflows/hlsl-test-all.yaml deleted file mode 100644 index b6530fe11b840..0000000000000 --- a/.github/workflows/hlsl-test-all.yaml +++ /dev/null @@ -1,87 +0,0 @@ -name: HLSL Test - -permissions: - contents: read - -on: - workflow_call: - inputs: - OffloadTest-branch: - description: 'Test Suite Branch' - required: false - default: 'main' - type: string - LLVM-ref: - description: 'LLVM Branch' - required: false - default: 'main' - type: string - SKU: - required: true - type: string - TestTarget: - required: false - default: 'check-hlsl' - type: string - -jobs: - build: - runs-on: ${{ inputs.SKU }} - steps: - - name: Checkout DXC - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - repository: Microsoft/DirectXShaderCompiler - ref: main - path: DXC - submodules: true - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: ${{ inputs.LLVM-branch }} - path: llvm-project - - name: Checkout OffloadTest - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - repository: llvm/offload-test-suite - ref: main - path: OffloadTest - - name: Checkout Golden Images - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - repository: llvm/offload-golden-images - ref: main - path: golden-images - - name: Setup Windows - if: runner.os == 'Windows' - uses: llvm/actions/setup-windows@main - with: - arch: amd64 - - name: Build DXC - run: | - cd DXC - mkdir build - cd build - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -C ${{ github.workspace }}/DXC/cmake/caches/PredefinedParams.cmake -C ${{ github.workspace }}/OffloadTest/cmake/caches/sccache.cmake -DHLSL_DISABLE_SOURCE_GENERATION=On ${{ github.workspace }}/DXC/ - ninja dxv llvm-dis - - name: Build LLVM - run: | - cd llvm-project - mkdir build - cd build - cmake -G Ninja -DDXIL_DIS=${{ github.workspace }}/DXC/build/bin/llvm-dis -DLLVM_INCLUDE_DXIL_TESTS=On -DCMAKE_BUILD_TYPE=Release -C ${{ github.workspace }}/llvm-project/clang/cmake/caches/HLSL.cmake -C ${{ github.workspace }}/OffloadTest/cmake/caches/sccache.cmake -DDXC_DIR=${{ github.workspace }}/DXC/build/bin -DLLVM_EXTERNAL_OFFLOADTEST_SOURCE_DIR=${{ github.workspace }}/OffloadTest -DLLVM_EXTERNAL_PROJECTS="OffloadTest" -DLLVM_LIT_ARGS="--xunit-xml-output=testresults.xunit.xml -v" -DGOLDENIMAGE_DIR=${{ github.workspace }}/golden-images ${{ github.workspace }}/llvm-project/llvm/ - ninja hlsl-test-depends llvm-test-depends clang-test-depends - - name: Run HLSL Tests - run: | - cd llvm-project - cd build - ninja check-llvm - ninja check-clang - ninja check-hlsl-unit - ninja ${{ inputs.TestTarget }} - - name: Publish Test Results - uses: EnricoMi/publish-unit-test-result-action/macos@170bf24d20d201b842d7a52403b73ed297e6645b # v2 - if: always() && runner.os == 'macOS' - with: - comment_mode: off - files: llvm-project/build/**/testresults.xunit.xml diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml deleted file mode 100644 index efd045990d013..0000000000000 --- a/.github/workflows/issue-release-workflow.yml +++ /dev/null @@ -1,69 +0,0 @@ -# This contains the workflow definitions that allow users to test backports -# to the release branch using comments on issues. -# -# /cherry-pick <...> -# -# This comment will attempt to cherry-pick the given commits to the latest -# release branch (release/Y.x) and if successful, push the result to a branch -# on github. -# -# /branch // -# -# This comment will create a pull request from to the latest release -# branch. - -name: Issue Release Workflow - -permissions: - contents: read - -on: - issue_comment: - types: - - created - - edited - issues: - types: - - opened - -env: - COMMENT_BODY: ${{ github.event.action == 'opened' && github.event.issue.body || github.event.comment.body }} - -jobs: - backport-commits: - name: Backport Commits - runs-on: ubuntu-24.04 - permissions: - issues: write - pull-requests: write - if: >- - (github.repository == 'llvm/llvm-project') && - !startswith(github.event.comment.body, '') && - contains(github.event.action == 'opened' && github.event.issue.body || github.event.comment.body, '/cherry-pick') - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - repository: llvm/llvm-project - # GitHub stores the token used for checkout and uses it for pushes - # too, but we want to use a different token for pushing, so we need - # to disable persist-credentials here. - persist-credentials: false - fetch-depth: 0 - - - name: Setup Environment - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - ./llvm/utils/git/github-automation.py --token ${{ github.token }} setup-llvmbot-git - - - name: Backport Commits - run: | - printf "%s" "$COMMENT_BODY" | - ./llvm/utils/git/github-automation.py \ - --repo "$GITHUB_REPOSITORY" \ - --token "${{ secrets.RELEASE_WORKFLOW_PR_CREATE }}" \ - release-workflow \ - --branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \ - --issue-number ${{ github.event.issue.number }} \ - --requested-by ${{ (github.event.action == 'opened' && github.event.issue.user.login) || github.event.comment.user.login }} \ - auto diff --git a/.github/workflows/issue-subscriber.yml b/.github/workflows/issue-subscriber.yml deleted file mode 100644 index de1c45c944960..0000000000000 --- a/.github/workflows/issue-subscriber.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Issue Subscriber - -on: - issues: - types: - - labeled - -permissions: - contents: read - -jobs: - auto-subscribe: - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - name: Checkout Automation Script - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: llvm/utils/git/ - ref: main - - - name: Setup Automation Script - working-directory: ./llvm/utils/git/ - run: | - pip install --require-hashes -r requirements.txt - - - name: Update watchers - working-directory: ./llvm/utils/git/ - # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable - env: - LABEL_NAME: ${{ github.event.label.name }} - run: | - python3 ./github-automation.py \ - --token '${{ secrets.ISSUE_SUBSCRIBER_TOKEN }}' \ - issue-subscriber \ - --issue-number '${{ github.event.issue.number }}' \ - --label-name "$LABEL_NAME" diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml deleted file mode 100644 index a2c4f58d6febe..0000000000000 --- a/.github/workflows/issue-write.yml +++ /dev/null @@ -1,157 +0,0 @@ -name: Comment on an issue - -on: - workflow_run: - workflows: - - "Check code formatting" - - "Check for private emails used in PRs" - - "PR Request Release Note" - types: - - completed - -permissions: - contents: read - -jobs: - pr-comment: - runs-on: ubuntu-24.04 - permissions: - pull-requests: write - if: > - github.event.workflow_run.event == 'pull_request' && - ( - github.event.workflow_run.conclusion == 'success' || - github.event.workflow_run.conclusion == 'failure' - ) - steps: - - name: Fetch Sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: | - .github/workflows/unprivileged-download-artifact/action.yml - sparse-checkout-cone-mode: false - - name: 'Download artifact' - uses: ./.github/workflows/unprivileged-download-artifact - id: download-artifact - with: - run-id: ${{ github.event.workflow_run.id }} - artifact-name: workflow-args - - - name: 'Comment on PR' - if: steps.download-artifact.outputs.artifact-id != '' - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - var fs = require('fs'); - const comments = JSON.parse(fs.readFileSync('./comments')); - if (!comments || comments.length == 0) { - return; - } - - let runInfo = await github.rest.actions.getWorkflowRun({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.payload.workflow_run.id - }); - - console.log(runInfo); - - - // Query to find the number of the pull request that triggered this job. - // The associated pull requests are based off of the branch name, so if - // you create a pull request for a branch, close it, and then create - // another pull request with the same branch, then this query will return - // two associated pull requests. This is why we have to fetch all the - // associated pull requests and then iterate through them to find the - // one that is open. - const gql_query = ` - query($repo_owner : String!, $repo_name : String!, $branch: String!) { - repository(owner: $repo_owner, name: $repo_name) { - ref (qualifiedName: $branch) { - associatedPullRequests(first: 100) { - nodes { - baseRepository { - owner { - login - } - } - number - state - } - } - } - } - } - ` - const gql_variables = { - repo_owner: runInfo.data.head_repository.owner.login, - repo_name: runInfo.data.head_repository.name, - branch: runInfo.data.head_branch - } - const gql_result = await github.graphql(gql_query, gql_variables); - console.log(gql_result); - // If the branch for the PR was deleted before this job has a chance - // to run, then the ref will be null. This can happen if someone: - // 1. Rebase the PR, which triggers some workflow. - // 2. Immediately merges the PR and deletes the branch. - // 3. The workflow finishes and triggers this job. - if (!gql_result.repository.ref) { - console.log("Ref has been deleted"); - return; - } - console.log(gql_result.repository.ref.associatedPullRequests.nodes); - - var pr_number = 0; - gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => { - - // The largest PR number is the one we care about. The only way - // to have more than one associated pull requests is if all the - // old pull requests are in the closed state. - if (pr.baseRepository.owner.login = context.repo.owner && pr.number > pr_number) { - pr_number = pr.number; - } - }); - if (pr_number == 0) { - console.log("Error retrieving pull request number"); - return; - } - - await comments.forEach(function (comment) { - if (comment.id) { - // Security check: Ensure that this comment was created by - // the github-actions bot, so a malicious input won't overwrite - // a user's comment. - github.rest.issues.getComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id - }).then((old_comment) => { - console.log(old_comment); - if (old_comment.data.user.login != "github-actions[bot]") { - console.log("Invalid comment id: " + comment.id); - return; - } - github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr_number, - comment_id: comment.id, - body: comment.body - }); - }); - } else { - github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr_number, - body: comment.body - }); - } - }); - - - name: Dump comments file - if: >- - always() && - steps.download-artifact.outputs.artifact-id != '' - run: cat comments diff --git a/.github/workflows/libc-fullbuild-tests.yml b/.github/workflows/libc-fullbuild-tests.yml deleted file mode 100644 index 9b2d8dd579702..0000000000000 --- a/.github/workflows/libc-fullbuild-tests.yml +++ /dev/null @@ -1,139 +0,0 @@ -# This workflow is for pre-commit testing of the LLVM-libc project. -name: LLVM-libc Pre-commit Fullbuild Tests -permissions: - contents: read -on: - pull_request: - branches: [ "main" ] - paths: - - 'libc/**' - - '.github/workflows/libc-fullbuild-tests.yml' - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - # Build basic linux configuration with Debug/Release/MinSizeRel and all - # other configurations in Debug only. - include: - - os: ubuntu-24.04 - build_type: Debug - ccache-variant: sccache - c_compiler: clang-21 - cpp_compiler: clang++-21 - target: x86_64-unknown-linux-llvm - include_scudo: ON - - os: ubuntu-24.04 - build_type: Release - ccache-variant: sccache - c_compiler: clang-21 - cpp_compiler: clang++-21 - target: x86_64-unknown-linux-llvm - include_scudo: ON - - os: ubuntu-24.04 - build_type: MinSizeRel - ccache-variant: sccache - c_compiler: clang-21 - cpp_compiler: clang++-21 - target: x86_64-unknown-linux-llvm - include_scudo: ON - # TODO: remove ccache logic when https://github.com/hendrikmuhs/ccache-action/issues/279 is resolved. - - os: ubuntu-24.04-arm - build_type: Debug - ccache-variant: ccache - c_compiler: clang-21 - cpp_compiler: clang++-21 - target: aarch64-unknown-linux-llvm - include_scudo: ON - - os: ubuntu-24.04 - build_type: Debug - ccache-variant: ccache - c_compiler: clang-21 - cpp_compiler: clang++-21 - target: x86_64-unknown-uefi-llvm - include_scudo: OFF - # TODO: add back gcc build when it is fixed - # - c_compiler: gcc - # cpp_compiler: g++ - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - # Libc's build is relatively small comparing with other components of LLVM. - # A fresh fullbuild takes about 190MiB of uncompressed disk space, which can - # be compressed into ~40MiB. Limiting the cache size to 1G should be enough. - # Prefer sccache as it is more modern. - # Do not use direct GHAC access even though it is supported by sccache. GHAC rejects - # frequent small object writes. - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - max-size: 1G - key: libc_fullbuild_${{ matrix.c_compiler }} - variant: ${{ matrix.ccache-variant }} - - # Notice: - # - MPFR is required by some of the mathlib tests. - # - Debian has a multilib setup, so we need to symlink the asm directory. - # For more information, see https://wiki.debian.org/Multiarch/LibraryPathOverview - - name: Prepare dependencies (Ubuntu) - run: | - wget https://apt.llvm.org/llvm.sh - chmod +x llvm.sh - sudo ./llvm.sh 21 - sudo apt-get update - sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev ninja-build linux-libc-dev - sudo ln -sf /usr/include/$(uname -p)-linux-gnu/asm /usr/include/asm - - - name: Set reusable strings - id: strings - shell: bash - run: | - echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - echo "build-install-dir=${{ github.workspace }}/install" >> "$GITHUB_OUTPUT" - - # Configure libc fullbuild with scudo. - # Use MinSizeRel to reduce the size of the build. - - name: Configure CMake - run: | - export RUNTIMES="libc" - - if [[ ${{ matrix.include_scudo}} == "ON" ]]; then - export RUNTIMES="$RUNTIMES;compiler-rt" - export CMAKE_FLAGS=" - -DLLVM_LIBC_INCLUDE_SCUDO=ON - -DCOMPILER_RT_BUILD_SCUDO_STANDALONE_WITH_LLVM_LIBC=ON - -DCOMPILER_RT_BUILD_GWP_ASAN=OFF - -DCOMPILER_RT_SCUDO_STANDALONE_BUILD_SHARED=OFF" - fi - - cmake -B ${{ steps.strings.outputs.build-output-dir }} \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} \ - -DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} \ - -DCMAKE_INSTALL_PREFIX=${{ steps.strings.outputs.build-install-dir }} \ - -DLLVM_RUNTIME_TARGETS=${{ matrix.target }} \ - -DLLVM_ENABLE_RUNTIMES="$RUNTIMES" \ - -DLLVM_LIBC_FULL_BUILD=ON \ - -G Ninja \ - -S ${{ github.workspace }}/runtimes \ - $CMAKE_FLAGS - - - name: Build - run: > - cmake - --build ${{ steps.strings.outputs.build-output-dir }} - --parallel - --target install - - - name: Test - # Skip UEFI tests until we have testing set up. - if: ${{ ! endsWith(matrix.target, '-uefi-llvm') }} - run: > - cmake - --build ${{ steps.strings.outputs.build-output-dir }} - --parallel - --target check-libc diff --git a/.github/workflows/libc-overlay-tests.yml b/.github/workflows/libc-overlay-tests.yml deleted file mode 100644 index f001daae030a3..0000000000000 --- a/.github/workflows/libc-overlay-tests.yml +++ /dev/null @@ -1,120 +0,0 @@ -# This workflow is for pre-commit testing of the LLVM-libc project. -name: LLVM-libc Pre-commit Overlay Tests -permissions: - contents: read -on: - pull_request: - branches: [ "main" ] - paths: - - 'libc/**' - - '.github/workflows/libc-overlay-tests.yml' - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. - fail-fast: false - matrix: - os: [ubuntu-24.04, ubuntu-24.04-arm, windows-2022, windows-2025, macos-14] - include: - # TODO: add linux gcc when it is fixed - - os: ubuntu-24.04 - ccache-variant: sccache - compiler: - c_compiler: clang - cpp_compiler: clang++ - # TODO: remove ccache logic when https://github.com/hendrikmuhs/ccache-action/issues/279 is resolved. - - os: ubuntu-24.04-arm - ccache-variant: ccache - compiler: - c_compiler: clang - cpp_compiler: clang++ - - os: windows-2022 - ccache-variant: sccache - compiler: - c_compiler: clang-cl - cpp_compiler: clang-cl - - os: windows-2025 - ccache-variant: sccache - compiler: - c_compiler: clang-cl - cpp_compiler: clang-cl - - os: macos-14 - ccache-variant: sccache - compiler: - c_compiler: clang - cpp_compiler: clang++ - - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - # Libc's build is relatively small comparing with other components of LLVM. - # A fresh linux overlay takes about 180MiB of uncompressed disk space, which can - # be compressed into ~40MiB. MacOS and Windows overlay builds are less than 10MiB - # after compression. Limiting the cache size to 1G should be enough. - # Prefer sccache as it is modern and it has a guarantee to work with MSVC. - # Do not use direct GHAC access even though it is supported by sccache. GHAC rejects - # frequent small object writes. - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - max-size: 1G - key: libc_overlay_build_${{ matrix.os }}_${{ matrix.compiler.c_compiler }} - variant: ${{ matrix.ccache-variant }} - - # MPFR is required by some of the mathlib tests. - - name: Prepare dependencies (Ubuntu) - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev ninja-build - - # Chocolatey is shipped with Windows runners. Windows Server 2025 recommends WinGet. - # Consider migrating to WinGet when Windows Server 2025 is available. - - name: Prepare dependencies (Windows) - if: runner.os == 'Windows' - run: | - choco install ninja - - - name: Prepare dependencies (macOS) - if: runner.os == 'macOS' - run: | - brew install ninja - - - name: Set reusable strings - id: strings - shell: bash - run: | - echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - # Use MinSizeRel to reduce the size of the build. - # Notice that CMP0141=NEW and MSVC_DEBUG_INFORMATION_FORMAT=Embedded are required - # by the sccache tool. - - name: Configure CMake - run: > - cmake -B ${{ steps.strings.outputs.build-output-dir }} - -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cpp_compiler }} - -DCMAKE_C_COMPILER=${{ matrix.compiler.c_compiler }} - -DCMAKE_BUILD_TYPE=Debug - -DCMAKE_C_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} - -DCMAKE_CXX_COMPILER_LAUNCHER=${{ matrix.ccache-variant }} - -DCMAKE_POLICY_DEFAULT_CMP0141=NEW - -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded - -DLLVM_ENABLE_RUNTIMES=libc - -G Ninja - -S ${{ github.workspace }}/runtimes - - - name: Build - run: > - cmake - --build ${{ steps.strings.outputs.build-output-dir }} - --parallel - --target libc - - - name: Test - run: > - cmake - --build ${{ steps.strings.outputs.build-output-dir }} - --parallel - --target check-libc diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml deleted file mode 100644 index 4d47c07f42205..0000000000000 --- a/.github/workflows/libclang-abi-tests.yml +++ /dev/null @@ -1,171 +0,0 @@ -name: libclang ABI Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/libclang-abi-tests.yml' - pull_request: - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/libclang-abi-tests.yml' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - abi-dump-setup: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - outputs: - BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} - ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} - ABI_LIBS: ${{ steps.vars.outputs.ABI_LIBS }} - BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} - LLVM_VERSION_MAJOR: ${{ steps.version.outputs.major }} - LLVM_VERSION_MINOR: ${{ steps.version.outputs.minor }} - LLVM_VERSION_PATCH: ${{ steps.version.outputs.patch }} - steps: - - name: Checkout source - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 250 - - - name: Get LLVM version - id: version - uses: ./.github/workflows/get-llvm-version - - - name: Setup Variables - id: vars - run: | - remote_repo='https://github.com/llvm/llvm-project' - if [ ${{ steps.version.outputs.patch }} -eq 0 ]; then - major_version=$(( ${{ steps.version.outputs.major }} - 1)) - baseline_ref="llvmorg-$major_version.1.0" - - # If there is a minor release, we want to use that as the base line. - minor_ref=$(git ls-remote --refs -t "$remote_repo" llvmorg-"$major_version".[1-9].[0-9] | tail -n1 | grep -o 'llvmorg-.\+' || true) - if [ -n "$minor_ref" ]; then - baseline_ref="$minor_ref" - else - # Check if we have a release candidate - rc_ref=$(git ls-remote --refs -t "$remote_repo" llvmorg-"$major_version".[1-9].[0-9]-rc* | tail -n1 | grep -o 'llvmorg-.\+' || true) - if [ -n "$rc_ref" ]; then - baseline_ref="$rc_ref" - fi - fi - { - echo "BASELINE_VERSION_MAJOR=$major_version" - echo "BASELINE_REF=$baseline_ref" - echo "ABI_HEADERS=clang-c" - echo "ABI_LIBS=libclang.so" - } >> "$GITHUB_OUTPUT" - else - { - echo "BASELINE_VERSION_MAJOR=${{ steps.version.outputs.major }}" - echo "BASELINE_REF=llvmorg-${{ steps.version.outputs.major }}.1.0" - echo "ABI_HEADERS=." - echo "ABI_LIBS=libclang.so libclang-cpp.so" - } >> "$GITHUB_OUTPUT" - fi - - abi-dump: - if: github.repository_owner == 'llvm' - needs: abi-dump-setup - runs-on: ubuntu-24.04 - strategy: - matrix: - name: - - build-baseline - - build-latest - include: - - name: build-baseline - llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} - ref: ${{ needs.abi-dump-setup.outputs.BASELINE_REF }} - repo: llvm/llvm-project - - name: build-latest - llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} - ref: ${{ github.sha }} - repo: ${{ github.repository }} - steps: - - name: Install Ninja - uses: llvm/actions/install-ninja@main - - name: Install abi-compliance-checker - run: | - sudo apt-get update - sudo apt-get install -y abi-dumper autoconf pkg-config - - name: Install universal-ctags - run: | - git clone https://github.com/universal-ctags/ctags.git - cd ctags - ./autogen.sh - ./configure - sudo make install - - name: Download source code - uses: llvm/actions/get-llvm-project-src@main - with: - ref: ${{ matrix.ref }} - repo: ${{ matrix.repo }} - - name: Configure - run: | - mkdir install - cmake -B build -S llvm -G Ninja -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX="$(pwd)"/install llvm - - name: Build - run: ninja -C build/ ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} install-clang-headers - - name: Dump ABI - run: | - parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} - for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do - # Remove symbol versioning from dumps, so we can compare across major versions. - sed -i 's/LLVM_[0-9]\+/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi - done - - name: Upload ABI file - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: ${{ matrix.name }} - path: '*${{ matrix.ref }}.abi' - - abi-compare: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - needs: - - abi-dump-setup - - abi-dump - steps: - - name: Download baseline - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # 4.1.8 - with: - name: build-baseline - path: build-baseline - - name: Download latest - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # 4.1.8 - with: - name: build-latest - path: build-latest - - - name: Install abi-compliance-checker - run: | - sudo apt-get update - sudo apt-get install -y abi-compliance-checker - - name: Compare ABI - run: | - for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do - abi-compliance-checker -lib $lib -old build-baseline/$lib*.abi -new build-latest/$lib*.abi - done - - name: Upload ABI Comparison - if: always() - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: compat-report-${{ github.sha }} - path: compat_reports/ diff --git a/.github/workflows/libclang-python-tests.yml b/.github/workflows/libclang-python-tests.yml deleted file mode 100644 index 43b50cec61716..0000000000000 --- a/.github/workflows/libclang-python-tests.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Libclang Python Binding Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'main' - paths: - - 'clang/bindings/python/**' - - 'clang/test/bindings/python/**' - - 'clang/tools/libclang/**' - - '.github/workflows/libclang-python-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - pull_request: - paths: - - 'clang/bindings/python/**' - - 'clang/test/bindings/python/**' - - 'clang/tools/libclang/**' - - '.github/workflows/libclang-python-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - -jobs: - check-clang-python: - # Build libclang and then run the libclang Python binding's unit tests. - name: Build and run Python unit tests - if: github.repository == 'llvm/llvm-project' - strategy: - fail-fast: false - matrix: - python-version: ["3.8", "3.13"] - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-clang-python - projects: clang - # There is an issue running on "windows-2019". - # See https://github.com/llvm/llvm-project/issues/76601#issuecomment-1873049082. - os_list: '["ubuntu-24.04"]' - python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml deleted file mode 100644 index ec937de02ca1a..0000000000000 --- a/.github/workflows/libcxx-build-and-test.yaml +++ /dev/null @@ -1,285 +0,0 @@ -# This file defines pre-commit CI for libc++, libc++abi, and libunwind (on Github). -# -# We split the configurations in multiple stages with the intent of saving compute time -# when a job fails early in the pipeline. This is why the jobs are marked as `continue-on-error: false`. -# We try to run the CI configurations with the most signal in the first stage. -# -# Stages 1 & 2 are meant to be "smoke tests", and are meant to catch most build/test failures quickly and without using -# too many resources. -# Stage 3 is "everything else", and is meant to catch breakages on more niche or unique configurations. -# -# Therefore, we "fail-fast" for any failures during stages 1 & 2, meaning any job failing cancels all other running jobs, -# under the assumption that if the "smoke tests" fail, then the other configurations will likely fail in the same way. -# However, stage 3 does not fail fast, as it's more likely that any one job failing is a flake or a configuration-specific -# -name: Build and Test libc++ -on: - pull_request: - paths: - - 'libcxx/**' - - 'libcxxabi/**' - - 'libunwind/**' - - 'runtimes/**' - - 'cmake/**' - - '.github/workflows/libcxx-build-and-test.yaml' - schedule: - # Run nightly at 08:00 UTC (aka 00:00 Pacific, aka 03:00 Eastern) - - cron: '0 8 * * *' - -permissions: - contents: read # Default everything to read-only - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - stage1: - if: github.repository_owner == 'llvm' - runs-on: llvm-premerge-libcxx-runners - continue-on-error: false - strategy: - fail-fast: false - matrix: - config: [ - 'frozen-cxx03-headers', - 'generic-cxx03', - 'generic-cxx26', - 'generic-modules' - ] - cc: [ 'clang-21' ] - cxx: [ 'clang++-21' ] - include: - - config: 'generic-gcc' - cc: 'gcc-15' - cxx: 'g++-15' - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: ${{ matrix.config }}.${{ matrix.cxx }} - run: libcxx/utils/ci/run-buildbot ${{ matrix.config }} - env: - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - if: always() - with: - name: ${{ matrix.config }}-${{ matrix.cxx }}-results - path: | - **/test-results.xml - **/*.abilist - **/CMakeConfigureLog.yaml - **/CMakeError.log - **/CMakeOutput.log - **/crash_diagnostics/* - stage2: - if: github.repository_owner == 'llvm' - runs-on: llvm-premerge-libcxx-runners - needs: [ stage1 ] - continue-on-error: false - strategy: - fail-fast: false - matrix: - config: [ - 'generic-cxx11', - 'generic-cxx14', - 'generic-cxx17', - 'generic-cxx20', - 'generic-cxx23' - ] - cc: [ 'clang-21' ] - cxx: [ 'clang++-21' ] - include: - - config: 'generic-gcc-cxx11' - cc: 'gcc-15' - cxx: 'g++-15' - - config: 'generic-cxx26' - cc: 'clang-20' - cxx: 'clang++-20' - - config: 'generic-cxx26' - cc: 'clang-19' - cxx: 'clang++-19' - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: ${{ matrix.config }} - run: libcxx/utils/ci/run-buildbot ${{ matrix.config }} - env: - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - if: always() # Upload artifacts even if the build or test suite fails - with: - name: ${{ matrix.config }}-${{ matrix.cxx }}-results - path: | - **/test-results.xml - **/*.abilist - **/CMakeConfigureLog.yaml - **/CMakeError.log - **/CMakeOutput.log - **/crash_diagnostics/* - stage3: - if: github.repository_owner == 'llvm' - needs: [ stage2 ] - continue-on-error: false - strategy: - fail-fast: false - max-parallel: 8 - matrix: - config: [ - 'generic-abi-unstable', - 'generic-hardening-mode-debug', - 'generic-hardening-mode-extensive', - 'generic-hardening-mode-fast', - 'generic-hardening-mode-fast-with-abi-breaks', - 'generic-merged', - 'generic-modules-cxx17-lsv', - 'generic-no-exceptions', - 'generic-no-experimental', - 'generic-no-filesystem', - 'generic-no-localization', - 'generic-no-terminal', - 'generic-no-random_device', - 'generic-no-threads', - 'generic-no-tzdb', - 'generic-no-unicode', - 'generic-no-wide-characters', - 'generic-no-rtti', - 'generic-optimized-speed', - 'generic-static', - 'bootstrapping-build' - ] - machine: [ 'llvm-premerge-libcxx-runners' ] - include: - - config: 'generic-cxx26' - machine: llvm-premerge-libcxx-runners - - config: 'generic-asan' - machine: llvm-premerge-libcxx-runners - - config: 'generic-tsan' - machine: llvm-premerge-libcxx-runners - - config: 'generic-ubsan' - machine: llvm-premerge-libcxx-runners - # Use a larger machine for MSAN to avoid timeout and memory allocation issues. - - config: 'generic-msan' - machine: llvm-premerge-libcxx-runners - runs-on: ${{ matrix.machine }} - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: ${{ matrix.config }} - run: libcxx/utils/ci/run-buildbot ${{ matrix.config }} - env: - CC: clang-21 - CXX: clang++-21 - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - if: always() - with: - name: ${{ matrix.config }}-results - path: | - **/test-results.xml - **/*.abilist - **/CMakeConfigureLog.yaml - **/CMakeError.log - **/CMakeOutput.log - **/crash_diagnostics/* - - macos: - needs: [ stage2 ] - strategy: - fail-fast: false - matrix: - include: - - config: generic-cxx03 - os: macos-15 - - config: generic-cxx23 - os: macos-15 - - config: generic-modules - os: macos-15 - - config: apple-configuration - os: macos-15 - # TODO: These jobs are intended to test back-deployment (building against ToT libc++ but running against an - # older system-provided libc++.dylib). Doing this properly would require building the test suite on a - # recent macOS using a recent Clang (hence recent Xcode), and then running the actual test suite on an - # older mac. We could do that by e.g. sharing artifacts between the two jobs. - # - # However, our Lit configuration currently doesn't provide a good way to do that in a batch, so our only - # alternative is to actually build on the same host that we're going to run on. Sadly, that doesn't work - # since older macOSes don't support newer Xcodes. For now, we run the "backdeployment" jobs on recent - # macOS versions as a way to avoid rotting that configuration, but it doesn't provide a lot of additional - # coverage. - - config: apple-system - os: macos-15 - - config: apple-system-hardened - os: macos-15 - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 - with: - # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md - xcode-version: '16.3' - - uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6 - - name: Build and test - run: | - python3 -m venv .venv - source .venv/bin/activate - python -m pip install psutil - bash libcxx/utils/ci/run-buildbot ${{ matrix.config }} - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 - if: always() # Upload artifacts even if the build or test suite fails - with: - name: macos-${{ matrix.config }}-results - path: | - **/test-results.xml - **/*.abilist - **/CMakeConfigureLog.yaml - **/CMakeError.log - **/CMakeOutput.log - **/crash_diagnostics/* - - windows: - runs-on: windows-2022 - needs: [ stage2 ] - strategy: - fail-fast: false - matrix: - include: - - { config: clang-cl-dll, mingw: false } - - { config: clang-cl-static, mingw: false } - - { config: clang-cl-no-vcruntime, mingw: false } - - { config: clang-cl-debug, mingw: false } - - { config: clang-cl-static-crt, mingw: false } - - { config: mingw-dll, mingw: true } - - { config: mingw-static, mingw: true } - - { config: mingw-dll-i686, mingw: true } - - { config: mingw-incomplete-sysroot, mingw: true } - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Install dependencies - run: | - choco install -y ninja - pip install psutil - - name: Install a current LLVM - if: ${{ matrix.mingw != true }} - run: | - choco install -y llvm --version=19.1.7 --allow-downgrade - - name: Install llvm-mingw - if: ${{ matrix.mingw == true }} - run: | - curl -LO https://github.com/mstorsjo/llvm-mingw/releases/download/20250114/llvm-mingw-20250114-ucrt-x86_64.zip - powershell Expand-Archive llvm-mingw*.zip -DestinationPath . - del llvm-mingw*.zip - mv llvm-mingw* c:\llvm-mingw - echo "c:\llvm-mingw\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append - - name: Simulate a from-scratch build of llvm-mingw - if: ${{ matrix.config == 'mingw-incomplete-sysroot' }} - run: | - rm -r c:\llvm-mingw\include\c++ - rm -r c:\llvm-mingw\*-w64-mingw32\lib\libc++* - rm -r c:\llvm-mingw\*-w64-mingw32\lib\libunwind* - - name: Add Git Bash to the path - run: | - echo "c:\Program Files\Git\usr\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append - - name: Set up the MSVC dev environment - if: ${{ matrix.mingw != true }} - uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - - name: Build and test - run: | - bash libcxx/utils/ci/run-buildbot ${{ matrix.config }} diff --git a/.github/workflows/libcxx-build-containers.yml b/.github/workflows/libcxx-build-containers.yml deleted file mode 100644 index 564a79341edb1..0000000000000 --- a/.github/workflows/libcxx-build-containers.yml +++ /dev/null @@ -1,70 +0,0 @@ -# This file defines an action that builds the various Docker images used to run -# libc++ CI whenever modifications to those Docker files are pushed to `main`. -# -# The images are pushed to the LLVM package registry at https://github.com/orgs/llvm/packages -# and tagged appropriately. The selection of which Docker image version is used by the libc++ -# CI nodes at any given point is controlled from the workflow files themselves. - -name: Build Docker images for libc++ CI - -permissions: - contents: read - -on: - push: - branches: - - main - paths: - - 'libcxx/utils/ci/**' - - '.github/workflows/libcxx-build-containers.yml' - pull_request: - branches: - - main - paths: - - 'libcxx/utils/ci/**' - - '.github/workflows/libcxx-build-containers.yml' - -jobs: - build-and-push: - runs-on: ubuntu-24.04 - if: github.repository_owner == 'llvm' - permissions: - packages: write - - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Build the Linux builder image - working-directory: libcxx/utils/ci - run: docker compose build actions-builder - env: - TAG: ${{ github.sha }} - - # - name: Build the Android builder image - # working-directory: libcxx/utils/ci - # run: docker compose build android-buildkite-builder - # env: - # TAG: ${{ github.sha }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Push the Linux builder image - if: github.event_name == 'push' - working-directory: libcxx/utils/ci - run: | - docker compose push actions-builder - env: - TAG: ${{ github.sha }} - - # - name: Push the Android builder image - # if: github.event_name == 'push' - # working-directory: libcxx/utils/ci - # run: | - # docker compose push android-buildkite-builder - # env: - # TAG: ${{ github.sha }} diff --git a/.github/workflows/libcxx-check-generated-files.yml b/.github/workflows/libcxx-check-generated-files.yml deleted file mode 100644 index 0226edd7aa17a..0000000000000 --- a/.github/workflows/libcxx-check-generated-files.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: "Check libc++ generated files" -on: - pull_request: - paths: - - 'libcxx/**' - -permissions: - contents: read - -jobs: - check_generated_files: - runs-on: ubuntu-24.04 - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Install dependencies - uses: aminya/setup-cpp@17c11551771948abc5752bbf3183482567c7caf0 # v1.1.1 - with: - clangformat: 17.0.1 - ninja: true - - - name: Check generated files - run: libcxx/utils/ci/run-buildbot check-generated-output diff --git a/.github/workflows/llvm-bugs.yml b/.github/workflows/llvm-bugs.yml deleted file mode 100644 index 5470662c97628..0000000000000 --- a/.github/workflows/llvm-bugs.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: LLVM Bugs notifier - -permissions: - contents: read - issues: read - -on: - issues: - types: - - opened - -jobs: - auto-subscribe: - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 - with: - node-version: 18 - check-latest: true - - run: npm install mailgun.js form-data - - name: Send notification - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 - env: - MAILGUN_API_KEY: ${{ secrets.LLVM_BUGS_KEY }} - with: - script: | - const Mailgun = require('mailgun.js'); - const formData = require('form-data'); - - const mailgun = new Mailgun(formData); - const DOMAIN = 'email.llvm.org'; - - const mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY }); - - github.rest.issues.get({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }) - .then((issue) => { - const payload = { - author : issue.data.user.login, - issue : issue.data.number, - title : issue.data.title, - url : issue.data.html_url, - labels : issue.data.labels.map((label) => label.name), - assignee : issue.data.assignees.map((assignee) => assignee.login), - body : issue.data.body - }; - - const data = { - from: 'LLVM Bugs ', - to: 'llvm-bugs@lists.llvm.org', - subject: `[Bug ${issue.data.number}] ${issue.data.title}`, - template: 'new-github-issue', - 'o:tracking-clicks': 'no', - 'h:X-Mailgun-Variables': JSON.stringify(payload) - }; - - return mg.messages.create(DOMAIN, data); - }) - .then((msg) => console.log(msg)); diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml deleted file mode 100644 index d40ed5babb459..0000000000000 --- a/.github/workflows/llvm-project-tests.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: LLVM Project Tests - -permissions: - contents: read - -on: - workflow_dispatch: - inputs: - build_target: - required: false - projects: - required: false - extra_cmake_args: - required: false - os_list: - required: false - default: '["ubuntu-24.04", "windows-2019", "macOS-13"]' - python_version: - required: false - type: string - default: '3.11' - workflow_call: - inputs: - build_target: - required: false - type: string - default: "all" - - projects: - required: true - type: string - - extra_cmake_args: - required: false - type: string - - os_list: - required: false - type: string - # Use windows-2019 due to: - # https://developercommunity.visualstudio.com/t/Prev-Issue---with-__assume-isnan-/1597317 - default: '["ubuntu-24.04", "windows-2019", "macOS-13"]' - - python_version: - required: false - type: string - default: '3.11' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - # If the group name here is the same as the group name in the workflow that includes - # this one, then the action will try to wait on itself and get stuck. - group: llvm-project-${{ github.workflow }}-${{ inputs.projects }}-${{ inputs.python_version }}${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - lit-tests: - name: Lit Tests - runs-on: ${{ matrix.os }} - container: - image: ${{(startsWith(matrix.os, 'ubuntu') && 'ghcr.io/llvm/ci-ubuntu-24.04:latest') || null}} - volumes: - - /mnt/:/mnt/ - strategy: - fail-fast: false - matrix: - os: ${{ fromJSON(inputs.os_list) }} - steps: - - name: Setup Windows - if: startsWith(matrix.os, 'windows') - uses: llvm/actions/setup-windows@main - with: - arch: amd64 - # On Windows, starting with win19/20220814.1, cmake choose the 32-bit - # python3.10.6 libraries instead of the 64-bit libraries when building - # lldb. Using this setup-python action to make 3.10 the default - # python fixes this. - - name: Setup Python - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 - with: - python-version: ${{ inputs.python_version }} - - name: Install Ninja - if: runner.os != 'Linux' - uses: llvm/actions/install-ninja@main - # actions/checkout deletes any existing files in the new git directory, - # so this needs to either run before ccache-action or it has to use - # clean: false. - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 250 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - # A full build of llvm, clang, lld, and lldb takes about 250MB - # of ccache space. There's not much reason to have more than this, - # because we usually won't need to save cache entries from older - # builds. Also, there is an overall 10GB cache limit, and each - # run creates a new cache entry so we want to ensure that we have - # enough cache space for all the tests to run at once and still - # fit under the 10 GB limit. - # Default to 2G to workaround: https://github.com/hendrikmuhs/ccache-action/issues/174 - max-size: 2G - key: ${{ matrix.os }} - variant: sccache - - name: Build and Test - env: - # Workaround for https://github.com/actions/virtual-environments/issues/5900. - # This should be a no-op for non-mac OSes - PKG_CONFIG_PATH: /usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig//12 - shell: bash - id: build-llvm - run: | - if [ "${{ runner.os }}" == "Linux" ]; then - builddir="/mnt/build/" - sudo mkdir -p $builddir - sudo chown gha $builddir - extra_cmake_args="-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang" - else - builddir="$(pwd)"/build - fi - if [ "${{ runner.os }}" == "macOS" ]; then - # Workaround test failure on some lld tests on MacOS - # https://github.com/llvm/llvm-project/issues/81967 - extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON" - fi - echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT" - cmake -G Ninja \ - -B "$builddir" \ - -S llvm \ - -DLLVM_ENABLE_PROJECTS="${{ inputs.projects }}" \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLVM_ENABLE_ASSERTIONS=ON \ - -DLLDB_INCLUDE_TESTS=OFF \ - -DLIBCLC_TARGETS_TO_BUILD="amdgcn--;amdgcn--amdhsa;r600--;nvptx--;nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl" \ - -DCMAKE_C_COMPILER_LAUNCHER=sccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ - $extra_cmake_args \ - ${{ inputs.extra_cmake_args }} - ninja -C "$builddir" '${{ inputs.build_target }}' - - - name: Build and Test libclc - if: "!startsWith(matrix.os, 'windows') && contains(inputs.projects, 'libclc')" - env: - LLVM_BUILDDIR: ${{ steps.build-llvm.outputs.llvm-builddir }} - run: | - # The libclc tests don't have a generated check target so all we can - # do is build it. - ninja -C "$LLVM_BUILDDIR" diff --git a/.github/workflows/llvm-project-workflow-tests.yml b/.github/workflows/llvm-project-workflow-tests.yml deleted file mode 100644 index a2539b279be0a..0000000000000 --- a/.github/workflows/llvm-project-workflow-tests.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This workflow will test the llvm-project-tests workflow in PRs -# targetting the main branch. Since this workflow doesn't normally -# run on main PRs, we need some way to test it to ensure new updates -# don't break it. - -name: LLVM Workflow Test - -permissions: - contents: read - -on: - pull_request: - branches: - - 'main' - paths: - - '.github/workflows/llvm-project-tests.yml' - - '.github/workflows/llvm-project-workflow-tests.yml' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - llvm-test: - if: github.repository_owner == 'llvm' - name: Build and Test - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-all - projects: clang;lld;libclc;lldb diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml deleted file mode 100644 index a9bd8db462cf7..0000000000000 --- a/.github/workflows/llvm-tests.yml +++ /dev/null @@ -1,185 +0,0 @@ -name: LLVM Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'llvm/**' - - '.github/workflows/llvm-tests.yml' - pull_request: - branches: - - 'release/**' - paths: - - 'llvm/**' - - '.github/workflows/llvm-tests.yml' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - abi-dump-setup: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - outputs: - BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} - ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} - BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} - BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} - LLVM_VERSION_MAJOR: ${{ steps.version.outputs.major }} - LLVM_VERSION_MINOR: ${{ steps.version.outputs.minor }} - LLVM_VERSION_PATCH: ${{ steps.version.outputs.patch }} - steps: - - name: Checkout source - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 250 - - - name: Get LLVM version - id: version - uses: ./.github/workflows/get-llvm-version - - - name: Setup Variables - id: vars - run: | - # C++ ABI: - # 18.1.0 we aren't doing ABI checks. - # 18.1.1 We want to check 18.1.0. - # C ABI: - # 18.1.0 We want to check 17.0.x - # 18.1.1 We want to check 18.1.0 - echo "BASELINE_VERSION_MINOR=1" >> "$GITHUB_OUTPUT" - if [ ${{ steps.version.outputs.patch }} -eq 0 ]; then - { - echo "BASELINE_VERSION_MAJOR=$(( ${{ steps.version.outputs.major }} - 1))" - echo "ABI_HEADERS=llvm-c" - } >> "$GITHUB_OUTPUT" - else - { - echo "BASELINE_VERSION_MAJOR=${{ steps.version.outputs.major }}" - echo "ABI_HEADERS=." - } >> "$GITHUB_OUTPUT" - fi - - abi-dump: - if: github.repository_owner == 'llvm' - needs: abi-dump-setup - runs-on: ubuntu-24.04 - strategy: - matrix: - name: - - build-baseline - - build-latest - include: - - name: build-baseline - llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} - ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MINOR }}.0 - repo: llvm/llvm-project - - name: build-latest - llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} - ref: ${{ github.sha }} - repo: ${{ github.repository }} - steps: - - name: Install Ninja - uses: llvm/actions/install-ninja@main - - name: Install abi-compliance-checker - run: | - sudo apt-get update - sudo apt-get -y install abi-dumper autoconf pkg-config - - name: Install universal-ctags - run: | - git clone https://github.com/universal-ctags/ctags.git - cd ctags - ./autogen.sh - ./configure - sudo make install - - name: Download source code - uses: llvm/actions/get-llvm-project-src@main - with: - ref: ${{ matrix.ref }} - repo: ${{ matrix.repo }} - - name: Configure - run: | - mkdir install - cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g1 -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g1 -Og" -DCMAKE_INSTALL_PREFIX="$(pwd)"/install llvm - - name: Build - # Need to run install-LLVM twice to ensure the symlink is installed (this is a bug). - run: | - ninja -C build install-LLVM - ninja -C build install-LLVM - ninja -C build install-llvm-headers - - name: Dump ABI - run: | - if [ "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" ]; then - nm ./install/lib/libLLVM.so | awk "/T _LLVM/ || /T LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" | cut -d ' ' -f 3 > llvm.symbols - # Even though the -symbols-list option doesn't seem to filter out the symbols, I believe it speeds up processing, so I'm leaving it in. - export EXTRA_ARGS="-symbols-list llvm.symbols" - else - touch llvm.symbols - fi - abi-dumper $EXTRA_ARGS -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o ${{ matrix.ref }}.abi ./install/lib/libLLVM.so - # Remove symbol versioning from dumps, so we can compare across major versions. - sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' ${{ matrix.ref }}.abi - - name: Upload ABI file - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: ${{ matrix.name }} - path: ${{ matrix.ref }}.abi - - - name: Upload symbol list file - if: matrix.name == 'build-baseline' - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: symbol-list - path: llvm.symbols - - abi-compare: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - needs: - - abi-dump-setup - - abi-dump - steps: - - name: Download baseline - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # 4.1.8 - with: - name: build-baseline - path: build-baseline - - name: Download latest - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # 4.1.8 - with: - name: build-latest - path: build-latest - - name: Download symbol list - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # 4.1.8 - with: - name: symbol-list - path: symbol-list - - - name: Install abi-compliance-checker - run: | - sudo apt-get update - sudo apt-get -y install abi-compliance-checker - - name: Compare ABI - run: | - if [ -s symbol-list/llvm.symbols ]; then - # This option doesn't seem to work with the ABI dumper, so passing it here. - export EXTRA_ARGS="-symbols-list symbol-list/llvm.symbols" - fi - # FIXME: Reading of gzip'd abi files on the GitHub runners stop - # working some time in March of 2021, likely due to a change in the - # runner's environment. - abi-compliance-checker $EXTRA_ARGS -l libLLVM.so -old build-baseline/*.abi -new build-latest/*.abi || test "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" - - name: Upload ABI Comparison - if: always() - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: compat-report-${{ github.sha }} - path: compat_reports/ diff --git a/.github/workflows/merged-prs.yml b/.github/workflows/merged-prs.yml deleted file mode 100644 index c771736389802..0000000000000 --- a/.github/workflows/merged-prs.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Add buildbot information to first PRs from new contributors" - -permissions: - contents: read - -on: - # It's safe to use pull_request_target here, because we aren't checking out - # code from the pull request branch. - # See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ - pull_request_target: - types: - - closed - -jobs: - buildbot_comment: - runs-on: ubuntu-24.04 - permissions: - pull-requests: write - if: >- - (github.repository == 'llvm/llvm-project') && - (github.event.pull_request.merged == true) - steps: - - name: Checkout Automation Script - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: llvm/utils/git/ - ref: main - - - name: Setup Automation Script - working-directory: ./llvm/utils/git/ - run: | - pip install --require-hashes -r requirements.txt - - - name: Add Buildbot information comment - working-directory: ./llvm/utils/git/ - run: | - python3 ./github-automation.py \ - --token '${{ secrets.GITHUB_TOKEN }}' \ - pr-buildbot-information \ - --issue-number "${{ github.event.pull_request.number }}" \ - --author "${{ github.event.pull_request.user.login }}" diff --git a/.github/workflows/new-issues.yml b/.github/workflows/new-issues.yml deleted file mode 100644 index 8480a657cc717..0000000000000 --- a/.github/workflows/new-issues.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Labeling new issues -on: - issues: - types: ['opened'] - -permissions: - contents: read - -jobs: - automate-issues-labels: - permissions: - issues: write - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - uses: llvm/actions/issue-labeler@main - with: - repo-token: ${{ secrets.ISSUE_SUBSCRIBER_TOKEN }} - configuration-path: .github/new-issues-labeler.yml - include-title: 1 - include-body: 0 - sync-labels: 0 - enable-versioned-regex: 0 diff --git a/.github/workflows/new-prs.yml b/.github/workflows/new-prs.yml deleted file mode 100644 index 935598e410dbb..0000000000000 --- a/.github/workflows/new-prs.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: "Labelling new pull requests" - -permissions: - contents: read - -on: - # It's safe to use pull_request_target here, because we aren't checking out - # code from the pull request branch. - # See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ - pull_request_target: - types: - - opened - - reopened - - ready_for_review - - synchronize - -jobs: - greeter: - runs-on: ubuntu-24.04 - permissions: - pull-requests: write - # Only comment on PRs that have been opened for the first time, by someone - # new to LLVM or to GitHub as a whole. Ideally we'd look for FIRST_TIMER - # or FIRST_TIME_CONTRIBUTOR, but this does not appear to work. Instead check - # that we do not have any of the other author associations. - # See https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=opened#pull_request - # for all the possible values. - if: >- - (github.repository == 'llvm/llvm-project') && - (github.event.action == 'opened') && - (github.event.pull_request.author_association != 'COLLABORATOR') && - (github.event.pull_request.author_association != 'CONTRIBUTOR') && - (github.event.pull_request.author_association != 'MANNEQUIN') && - (github.event.pull_request.author_association != 'MEMBER') && - (github.event.pull_request.author_association != 'OWNER') - steps: - - name: Checkout Automation Script - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: llvm/utils/git/ - ref: main - - - name: Setup Automation Script - working-directory: ./llvm/utils/git/ - run: | - pip install --require-hashes -r requirements.txt - - - name: Greet Author - working-directory: ./llvm/utils/git/ - run: | - python3 ./github-automation.py \ - --token '${{ secrets.GITHUB_TOKEN }}' \ - pr-greeter \ - --issue-number "${{ github.event.pull_request.number }}" - - automate-prs-labels: - # Greet first so that only the author gets that notification. - needs: greeter - runs-on: ubuntu-24.04 - # Ignore PRs with more than 10 commits. Pull requests with a lot of - # commits tend to be accidents usually when someone made a mistake while trying - # to rebase. We want to ignore these pull requests to avoid excessive - # notifications. - # always() means that even if greeter is skipped, this job will run. - if: > - always() && github.repository == 'llvm/llvm-project' && - github.event.pull_request.draft == false && - github.event.pull_request.commits < 10 - steps: - - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 - with: - configuration-path: .github/new-prs-labeler.yml - # workaround for https://github.com/actions/labeler/issues/112 - sync-labels: '' - repo-token: ${{ secrets.ISSUE_SUBSCRIBER_TOKEN }} diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 70bcaafbd0cf3..ae7df60b9113a 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -6,17 +6,18 @@ permissions: on: pull_request: branches: - - main - - 'users/**' + - npu/main + - npu/release/20.x + - npu/release/21.x + jobs: code_formatter: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest timeout-minutes: 30 concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true - if: github.repository == 'llvm/llvm-project' steps: - name: Fetch LLVM sources uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 diff --git a/.github/workflows/pr-request-release-note.yml b/.github/workflows/pr-request-release-note.yml deleted file mode 100644 index 57425e04ec2f4..0000000000000 --- a/.github/workflows/pr-request-release-note.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: PR Request Release Note - -permissions: - contents: read - -on: - pull_request: - types: - - closed - -jobs: - request-release-note: - if: >- - github.repository_owner == 'llvm' && - startsWith(github.ref, 'refs/heads/release') - - runs-on: ubuntu-24.04 - steps: - # We need to pull the script from the main branch, so that we ensure - # we get the latest version of this script. - - name: Checkout Scripts - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - sparse-checkout: | - llvm/utils/git/requirements.txt - llvm/utils/git/github-automation.py - sparse-checkout-cone-mode: false - - - name: Install Dependencies - run: | - pip install --require-hashes -r llvm/utils/git/requirements.txt - - - name: Request Release Note - env: - # We need to use an llvmbot token here, because we are mentioning a user. - GITHUB_TOKEN: ${{ github.token }} - run: | - python3 llvm/utils/git/github-automation.py \ - --repo "$GITHUB_REPOSITORY" \ - --token "$GITHUB_TOKEN" \ - request-release-note \ - --pr-number ${{ github.event.pull_request.number}} - - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - if: always() - with: - name: workflow-args - path: | - comments diff --git a/.github/workflows/pr-subscriber.yml b/.github/workflows/pr-subscriber.yml deleted file mode 100644 index f558da8a8fe0e..0000000000000 --- a/.github/workflows/pr-subscriber.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: PR Subscriber - -on: - pull_request_target: - types: - - labeled - -permissions: - contents: read - -jobs: - auto-subscribe: - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - name: Checkout Automation Script - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - sparse-checkout: llvm/utils/git/ - ref: main - - - name: Setup Automation Script - working-directory: ./llvm/utils/git/ - run: | - pip install --require-hashes -r requirements.txt - - - name: Update watchers - working-directory: ./llvm/utils/git/ - run: | - python3 ./github-automation.py \ - --token '${{ secrets.ISSUE_SUBSCRIBER_TOKEN }}' \ - pr-subscriber \ - --issue-number "${{ github.event.number }}" \ - --label-name "${{ github.event.label.name }}" diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml deleted file mode 100644 index f7a48304b82b0..0000000000000 --- a/.github/workflows/premerge.yaml +++ /dev/null @@ -1,171 +0,0 @@ -name: CI Checks - -permissions: - contents: read - -on: - pull_request: - types: - - opened - - synchronize - - reopened - # When a PR is closed, we still start this workflow, but then skip - # all the jobs, which makes it effectively a no-op. The reason to - # do this is that it allows us to take advantage of concurrency groups - # to cancel in progress CI jobs whenever the PR is closed. - - closed - push: - branches: - - 'release/**' - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: true - -jobs: - premerge-checks-linux: - name: Build and Test Linux - if: >- - github.repository_owner == 'llvm' && - (github.event_name != 'pull_request' || github.event.action != 'closed') - runs-on: llvm-premerge-linux-runners - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 2 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - max-size: "2000M" - - name: Build and Test - # Mark the job as a success even if the step fails so that people do - # not get notified while the new premerge pipeline is in an - # experimental state. - run: | - git config --global --add safe.directory '*' - - source <(git diff --name-only HEAD~1...HEAD | python3 .ci/compute_projects.py) - - if [[ "${projects_to_build}" == "" ]]; then - echo "No projects to build" - exit 0 - fi - - echo "Building projects: ${projects_to_build}" - echo "Running project checks targets: ${project_check_targets}" - echo "Building runtimes: ${runtimes_to_build}" - echo "Running runtimes checks targets: ${runtimes_check_targets}" - echo "Running runtimes checks requiring reconfiguring targets: ${runtimes_check_targets_needs_reconfig}" - - export CC=/opt/llvm/bin/clang - export CXX=/opt/llvm/bin/clang++ - - ./.ci/monolithic-linux.sh "${projects_to_build}" "${project_check_targets}" "${runtimes_to_build}" "${runtimes_check_targets}" "${runtimes_check_targets_needs_reconfig}" - - name: Upload Artifacts - if: '!cancelled()' - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: Premerge Artifacts (Linux) - path: artifacts/ - retention-days: 5 - include-hidden-files: 'true' - - premerge-checks-windows: - name: Build and Test Windows - if: >- - github.repository_owner == 'llvm' && - (github.event_name != 'pull_request' || github.event.action != 'closed') - runs-on: llvm-premerge-windows-runners - defaults: - run: - shell: bash - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 2 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - variant: "sccache" - max-size: "2000M" - - name: Compute Projects - id: vars - run: | - source <(git diff --name-only HEAD~1...HEAD | python .ci/compute_projects.py) - - if [[ "${projects_to_build}" == "" ]]; then - echo "No projects to build" - fi - - echo "Building projects: ${projects_to_build}" - echo "Running project checks targets: ${project_check_targets}" - - echo "windows-projects=${projects_to_build}" >> $GITHUB_OUTPUT - echo "windows-check-targets=${project_check_targets}" >> $GITHUB_OUTPUT - - name: Build and Test - # Mark the job as a success even if the step fails so that people do - # not get notified while the new premerge pipeline is in an - # experimental state. - if: ${{ steps.vars.outputs.windows-projects != '' }} - shell: cmd - run: | - call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64 - bash .ci/monolithic-windows.sh "${{ steps.vars.outputs.windows-projects }}" "${{ steps.vars.outputs.windows-check-targets }}" - - name: Upload Artifacts - if: '!cancelled()' - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: Premerge Artifacts (Windows) - path: artifacts/ - retention-days: 5 - include-hidden-files: 'true' - - premerge-check-macos: - name: MacOS Premerge Checks - runs-on: macos-14 - if: >- - github.repository_owner == 'llvm' && - (startswith(github.ref_name, 'release/') || - startswith(github.base_ref, 'release/')) && - (github.event_name != 'pull_request' || github.event.action != 'closed') - steps: - - name: Checkout LLVM - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 2 - - name: Setup ccache - uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 - with: - max-size: "2000M" - - name: Install Ninja - uses: llvm/actions/install-ninja@main - - name: Build and Test - run: | - source <(git diff --name-only HEAD~2..HEAD | python3 .ci/compute_projects.py) - - if [[ "${projects_to_build}" == "" ]]; then - echo "No projects to build" - exit 0 - fi - - echo "Building projects: ${projects_to_build}" - echo "Running project checks targets: ${project_check_targets}" - - # -DLLVM_DISABLE_ASSEMBLY_FILES=ON is for - # https://github.com/llvm/llvm-project/issues/81967 - # Disable sharding in lit so that the LIT_XFAIL environment var works. - cmake -G Ninja \ - -B build \ - -S llvm \ - -DLLVM_ENABLE_PROJECTS="${projects_to_build}" \ - -DLLVM_DISABLE_ASSEMBLY_FILES=ON \ - -DCMAKE_BUILD_TYPE=Release \ - -DLLDB_INCLUDE_TESTS=OFF \ - -DLLVM_ENABLE_ASSERTIONS=ON \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - - # The libcxx tests fail, so we are skipping the runtime targets. - ninja -C build ${project_check_targets} diff --git a/.github/workflows/release-asset-audit.py b/.github/workflows/release-asset-audit.py deleted file mode 100644 index 23b901a476dc0..0000000000000 --- a/.github/workflows/release-asset-audit.py +++ /dev/null @@ -1,102 +0,0 @@ -import github -import re -import sys - -_SPECIAL_CASE_BINARIES = { - "keith": {"clang+llvm-18.1.8-arm64-apple-macos11.tar.xz"}, -} - - -def _is_valid(uploader_name, valid_uploaders, asset_name): - if uploader_name in valid_uploaders: - return True - - if uploader_name in _SPECIAL_CASE_BINARIES: - return asset_name in _SPECIAL_CASE_BINARIES[uploader_name] - - return False - - -def _get_uploaders(release_version): - # Until llvm 18, assets were uploaded by community members, the release managers - # and the GitHub Actions bot. - if release_version <= 18: - return set( - [ - "DimitryAndric", - "stefanp-synopsys", - "lei137", - "omjavaid", - "nicolerabjohn", - "amy-kwan", - "mandlebug", - "zmodem", - "androm3da", - "tru", - "rovka", - "rorth", - "quinnlp", - "kamaub", - "abrisco", - "jakeegan", - "maryammo", - "tstellar", - "github-actions[bot]", - ] - ) - # llvm 19 and beyond, only the release managers, bot and a much smaller - # number of community members. - elif release_version >= 19: - return set( - [ - "zmodem", - "omjavaid", - "tru", - "tstellar", - "github-actions[bot]", - ] - ) - - -def _get_major_release_version(release_title): - # All release titles are of the form "LLVM X.Y.Z(-rcN)". - match = re.match("LLVM ([0-9]+)\.", release_title) - if match is None: - _write_comment_and_exit_with_error( - f'Could not parse release version from release title "{release_title}".' - ) - else: - return int(match.groups()[0]) - - -def _write_comment_and_exit_with_error(comment): - with open("comment", "w") as file: - file.write(comment) - sys.exit(1) - - -def main(): - token = sys.argv[1] - - gh = github.Github(login_or_token=token) - repo = gh.get_repo("llvm/llvm-project") - - for release in repo.get_releases(): - print("Release:", release.title) - uploaders = _get_uploaders(_get_major_release_version(release.title)) - for asset in release.get_assets(): - created_at = asset.created_at - updated_at = ( - "" if asset.created_at == asset.updated_at else asset.updated_at - ) - print( - f"{asset.name} : {asset.uploader.login} [{created_at} {updated_at}] ( {asset.download_count} )" - ) - if not _is_valid(asset.uploader.login, uploaders, asset.name): - _write_comment_and_exit_with_error( - f"@{asset.uploader.login} is not a valid uploader." - ) - - -if __name__ == "__main__": - main() diff --git a/.github/workflows/release-asset-audit.yml b/.github/workflows/release-asset-audit.yml deleted file mode 100644 index 8112d8a140810..0000000000000 --- a/.github/workflows/release-asset-audit.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Release Asset Audit - -on: - workflow_dispatch: - release: - schedule: - # * is a special character in YAML so you have to quote this string - # Run once an hour - - cron: '5 * * * *' - - pull_request: - paths: - - ".github/workflows/release-asset-audit.py" - - ".github/workflows/release-asset-audit.yml" - -permissions: - contents: read # Default everything to read-only - -jobs: - audit: - name: "Release Asset Audit" - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6 - - name: "Run Audit Script" - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - python3 ./.github/workflows/release-asset-audit.py $GITHUB_TOKEN - - name: "File Issue" - if: >- - github.event_name != 'pull_request' && - failure() - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 - with: - github-token: ${{ secrets.ISSUE_SUBSCRIBER_TOKEN }} - script: | - var fs = require('fs'); - var body = '' - if (fs.existsSync('./comment')) { - body = fs.readFileSync('./comment') + "\n\n"; - } - body = body + `\n\nhttps://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}` - - const issue = await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: "Release Asset Audit Failed", - labels: ['infrastructure'], - body: body - }); - console.log(issue); diff --git a/.github/workflows/release-binaries-all.yml b/.github/workflows/release-binaries-all.yml deleted file mode 100644 index 0b52a08202f1a..0000000000000 --- a/.github/workflows/release-binaries-all.yml +++ /dev/null @@ -1,105 +0,0 @@ -name: Release Binaries All - -permissions: - contents: read # Default everything to read-only - -on: - workflow_dispatch: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload binaries to the release page' - required: true - default: false - type: boolean - - workflow_call: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload binaries to the release page' - required: true - default: false - type: boolean - secrets: - RELEASE_TASKS_USER_TOKEN: - description: "Secret used to check user permissions." - required: false - - pull_request: - types: - - opened - - synchronize - - reopened - # When a PR is closed, we still start this workflow, but then skip - # all the jobs, which makes it effectively a no-op. The reason to - # do this is that it allows us to take advantage of concurrency groups - # to cancel in progress CI jobs whenever the PR is closed. - - closed - paths: - - '.github/workflows/release-binaries-all.yml' - - '.github/workflows/release-binaries.yml' - - '.github/workflows/release-binaries-setup-stage/*' - - '.github/workflows/release-binaries-save-stage/*' - - 'clang/cmake/caches/Release.cmake' - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || 'dispatch' }} - cancel-in-progress: True - -jobs: - setup-variables: - if: >- - (github.event_name != 'pull_request' || github.event.action != 'closed') - runs-on: ubuntu-24.04 - outputs: - release-version: ${{ steps.vars.outputs.release-version }} - upload: ${{ steps.vars.outputs.upload }} - steps: - - shell: bash - id: vars - run: | - upload="${{ inputs.upload }}" - release_version="${{ inputs.release-version }}" - if [ "${{ github.event_name }}" = "pull_request" ]; then - upload="false" - release_version="" - fi - echo "release-version=$release_version" >> "$GITHUB_OUTPUT" - echo "upload=$upload" >> "$GITHUB_OUTPUT" - - release-binaries-all: - name: Build Release Binaries - needs: - - setup-variables - permissions: - contents: write # For release uploads - id-token: write # For artifact attestations - attestations: write # For artifact attestations - strategy: - fail-fast: false - matrix: - # We use ubuntu-22.04 rather than the latest version to make the built - # binaries more portable (eg functional aginast older glibc). - runs-on: - - ubuntu-22.04 - - ubuntu-22.04-arm - - macos-13 - - macos-14 - - uses: ./.github/workflows/release-binaries.yml - with: - release-version: "${{ needs.setup-variables.outputs.release-version }}" - upload: ${{ needs.setup-variables.outputs.upload == 'true'}} - runs-on: "${{ matrix.runs-on }}" - secrets: - # This will be empty for pull_request events, but that's fine, because - # the release-binaries workflow does not use this secret for the - # pull_request event. - RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} diff --git a/.github/workflows/release-binaries-save-stage/action.yml b/.github/workflows/release-binaries-save-stage/action.yml deleted file mode 100644 index f08088c7bc56f..0000000000000 --- a/.github/workflows/release-binaries-save-stage/action.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Save Stage -description: >- - Upload the source and binary directories from a build stage so that they - can be re-used in the next stage. This action is used to the release - binaries workflow into multiple stages to avoid the 6 hour timeout on - the GitHub hosted runners. -inputs: - build-prefix: - description: "Directory containing the build directory." - required: true - type: 'string' - -permissions: - contents: read - -runs: - using: "composite" - steps: - # We need to create an archive of the build directory, because it has too - # many files to upload. - - name: Package Build and Source Directories - shell: bash - run: | - # Remove .git/config to avoid leaking GITHUB_TOKEN stored there. - # See https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/ - rm -Rf .git/config - # Windows does not support symlinks, so we need to dereference them. - tar --exclude build/ ${{ (runner.os == 'Windows' && '-h') || '' }} -c . | zstd -T0 -c > ../llvm-project.tar.zst - mv ../llvm-project.tar.zst . - tar -C ${{ inputs.build-prefix }} -c build/ | zstd -T0 -c > build.tar.zst - - - name: Upload Stage 1 Source - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - with: - name: ${{ runner.os }}-${{ runner.arch }}-${{ github.job }}-source - path: llvm-project.tar.zst - retention-days: 2 - - - name: Upload Stage 1 Build Dir - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - with: - name: ${{ runner.os}}-${{ runner.arch }}-${{ github.job }}-build - path: build.tar.zst - retention-days: 2 diff --git a/.github/workflows/release-binaries-setup-stage/action.yml b/.github/workflows/release-binaries-setup-stage/action.yml deleted file mode 100644 index f5e5db27e6595..0000000000000 --- a/.github/workflows/release-binaries-setup-stage/action.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Setup Stage -description: >- - Setup the next stage of the release binaries workflow. This sets up the - environment correctly for a new stage of the release binaries workflow - and also restores the source and build directory from the previous stage. - -inputs: - previous-artifact: - description: >- - A unique descriptor for the artifact from the previous stage. This will - be used to construct the final artifact pattern, which is: - $RUNNER_OS-$RUNNER_ARCH-$PREVIOUS_ARTIFACT-* - required: false - type: 'string' - -outputs: - build-prefix: - description: "Directory containing the build directory." - value: ${{ steps.build-prefix.outputs.build-prefix }} - -runs: - using: "composite" - steps: - - name: Install Ninja - uses: llvm/actions/install-ninja@22e9f909d35b50bd1181709564bfe816eaeaae81 # main - - - name: Setup Windows - if: startsWith(runner.os, 'Windows') - uses: llvm/actions/setup-windows@main - with: - arch: amd64 - - - name: Set Build Prefix - id: build-prefix - shell: bash - run: | - build_prefix=`pwd` - if [ "${{ runner.os }}" = "Linux" ]; then - sudo chown $USER:$USER /mnt/ - build_prefix=/mnt/ - fi - echo "build-prefix=$build_prefix" >> $GITHUB_OUTPUT - - - name: Download Previous Stage Artifact - if: ${{ inputs.previous-artifact }} - id: download - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 - with: - pattern: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.previous-artifact }}-* - merge-multiple: true - - - name: Unpack Artifact - if: ${{ steps.download.outputs.download-path }} - shell: bash - run: | - tar --zstd -xf llvm-project.tar.zst - rm llvm-project.tar.zst - tar --zstd -C ${{ steps.build-prefix.outputs.build-prefix}} -xf build.tar.zst - rm build.tar.zst diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml deleted file mode 100644 index c113b42dc8ed4..0000000000000 --- a/.github/workflows/release-binaries.yml +++ /dev/null @@ -1,357 +0,0 @@ -name: Release Binaries - -on: - workflow_dispatch: - inputs: - release-version: - description: 'Release Version' - required: false - type: string - upload: - description: 'Upload binaries to the release page' - required: true - default: false - type: boolean - runs-on: - description: "Runner to use for the build" - required: true - type: choice - # We use ubuntu-22.04 rather than the latest version to make the built - # binaries more portable (eg functional aginast older glibc). - options: - - ubuntu-22.04 - - ubuntu-22.04-arm - - macos-13 - - macos-14 - - workflow_call: - inputs: - release-version: - description: 'Release Version' - required: false - type: string - upload: - description: 'Upload binaries to the release page' - required: true - default: false - type: boolean - runs-on: - description: "Runner to use for the build" - required: true - type: string - secrets: - RELEASE_TASKS_USER_TOKEN: - description: "Secret used to check user permissions." - required: false - - -permissions: - contents: read # Default everything to read-only - -jobs: - prepare: - name: Prepare to build binaries - runs-on: ${{ inputs.runs-on }} - if: github.repository_owner == 'llvm' - outputs: - release-version: ${{ steps.vars.outputs.release-version }} - ref: ${{ steps.vars.outputs.ref }} - upload: ${{ steps.vars.outputs.upload }} - target-cmake-flags: ${{ steps.vars.outputs.target-cmake-flags }} - ccache: ${{ steps.vars.outputs.ccache }} - build-flang: ${{ steps.vars.outputs.build-flang }} - release-binary-basename: ${{ steps.vars.outputs.release-binary-basename }} - release-binary-filename: ${{ steps.vars.outputs.release-binary-filename }} - build-runs-on: ${{ steps.vars.outputs.build-runs-on }} - test-runs-on: ${{ steps.vars.outputs.build-runs-on }} - - steps: - # It's good practice to use setup-python, but this is also required on macos-14 - # due to https://github.com/actions/runner-images/issues/10385 - - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f - with: - python-version: '3.12' - - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Install Dependencies - shell: bash - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - - - name: Check Permissions - if: github.event_name != 'pull_request' - env: - GITHUB_TOKEN: ${{ github.token }} - USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - shell: bash - run: | - ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user "$GITHUB_ACTOR" --user-token "$USER_TOKEN" check-permissions - - - name: Collect Variables - id: vars - shell: bash - # In order for the test-release.sh script to run correctly, the LLVM - # source needs to be at the following location relative to the build dir: - # | X.Y.Z-rcN | ./rcN/llvm-project - # | X.Y.Z | ./final/llvm-project - # - # We also need to set divergent flags based on the release version: - # | X.Y.Z-rcN | -rc N -test-asserts - # | X.Y.Z | -final - run: | - trimmed=$(echo ${{ inputs.release-version }} | xargs) - if [ -n "$trimmed" ]; then - release_version="$trimmed" - ref="llvmorg-$release_version" - else - release_version="${{ (github.event_name == 'pull_request' && format('PR{0}', github.event.pull_request.number)) || 'CI'}}-$GITHUB_SHA" - ref="$GITHUB_SHA" - fi - if [ -n "${{ inputs.upload }}" ]; then - upload="${{ inputs.upload }}" - else - upload="false" - fi - echo "release-version=$release_version">> $GITHUB_OUTPUT - echo "ref=$ref" >> $GITHUB_OUTPUT - echo "upload=$upload" >> $GITHUB_OUTPUT - - release_binary_basename="LLVM-$release_version-$RUNNER_OS-$RUNNER_ARCH" - echo "release-binary-basename=$release_binary_basename" >> $GITHUB_OUTPUT - echo "release-binary-filename=$release_binary_basename.tar.xz" >> $GITHUB_OUTPUT - - target="$RUNNER_OS-$RUNNER_ARCH" - # The hendrikmuhs/ccache-action action does not support installing sccache - # on arm64 Linux. - if [ "$target" = "Linux-ARM64" ]; then - echo ccache=ccache >> $GITHUB_OUTPUT - else - echo ccache=sccache >> $GITHUB_OUTPUT - fi - - # The macOS builds try to cross compile some libraries so we need to - # add extra CMake args to disable them. - # See https://github.com/llvm/llvm-project/issues/99767 - if [ "$RUNNER_OS" = "macOS" ]; then - target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF" - if [ "$RUNNER_ARCH" = "ARM64" ]; then - arches=arm64 - else - arches=x86_64 - # Disable Flang builds on macOS x86_64. The FortranLower library takes - # 2-3 hours to build on macOS, much slower than on Linux. - # The long build time causes the release build to time out on x86_64, - # so we need to disable flang there. - target_cmake_flags="$target_cmake_flags -DLLVM_RELEASE_ENABLE_PROJECTS='clang;lld;lldb;clang-tools-extra;polly;mlir'" - fi - target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_ARCHS=$arches -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_BUILTIN_ARCHS=$arches" - fi - - build_flang="true" - - if [ "$RUNNER_OS" = "Windows" ]; then - # The build times out on Windows, so we need to disable LTO. - target_cmake_flags="$target_cmake_flags -DLLVM_RELEASE_ENABLE_LTO=OFF" - fi - - echo "target-cmake-flags=$target_cmake_flags" >> $GITHUB_OUTPUT - echo "build-flang=$build_flang" >> $GITHUB_OUTPUT - case "${{ inputs.runs-on }}" in - ubuntu-22.04*) - build_runs_on="depot-${{ inputs.runs-on }}-16" - test_runs_on=$build_runs_on - ;; - macos-13) - if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then - build_runs_on="${{ inputs.runs-on }}" - else - build_runs_on="macos-13-large" - fi - test_runs_on="${{ inputs.runs-on }}" - ;; - macos-14) - if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then - build_runs_on="${{ inputs.runs-on }}" - else - build_runs_on="depot-macos-14" - fi - test_runs_on="${{ inputs.runs-on }}" - ;; - *) - test_runs_on="${{ inputs.runs-on }}" - build_runs_on=$test_runs_on - ;; - esac - echo "build-runs-on=$build_runs_on" >> $GITHUB_OUTPUT - echo "test-runs-on=$test_runs_on" >> $GITHUB_OUTPUT - - build-release-package: - name: "Build Release Package" - needs: prepare - if: github.repository_owner == 'llvm' - runs-on: ${{ needs.prepare.outputs.build-runs-on }} - steps: - - - name: Checkout Actions - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: ${{ (github.event_name == 'pull_request' && github.sha) || 'main' }} - sparse-checkout: | - .github/workflows/ - sparse-checkout-cone-mode: false - # Check out outside of working directory so the source checkout doesn't - # remove it. - path: workflows - - # actions/checkout does not support paths outside of the GITHUB_WORKSPACE. - # Also, anything that we put inside of GITHUB_WORKSPACE will be overwritten - # by future actions/checkout steps. Therefore, in order to checkout the - # latest actions from main, we need to first checkout out the actions inside of - # GITHUB_WORKSPACE (see previous step), then use actions/checkout to checkout - # the code being built and the move the actions from main back into GITHUB_WORKSPACE, - # becasue the uses on composite actions only reads workflows from inside GITHUB_WORKSPACE. - - shell: bash - run: mv workflows ../workflows-main - - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: ${{ needs.prepare.outputs.ref }} - - - name: Copy main workflows - shell: bash - run: | - mv ../workflows-main . - - - name: Setup Stage - id: setup-stage - uses: ./workflows-main/.github/workflows/release-binaries-setup-stage - - - name: Configure - id: build - shell: bash - env: - CCACHE_BIN: ${{ needs.prepare.outputs.ccache }} - run: | - # There were some issues on the ARM64 MacOS runners with trying to build x86 object, - # so we need to set some extra cmake flags to disable this. - cmake -G Ninja -S llvm -B ${{ steps.setup-stage.outputs.build-prefix }}/build \ - ${{ needs.prepare.outputs.target-cmake-flags }} \ - -C clang/cmake/caches/Release.cmake \ - -DBOOTSTRAP_LLVM_PARALLEL_LINK_JOBS=1 \ - -DBOOTSTRAP_BOOTSTRAP_CPACK_PACKAGE_FILE_NAME="${{ needs.prepare.outputs.release-binary-basename }}" - - - name: Build - shell: bash - run: | - ninja -v -C ${{ steps.setup-stage.outputs.build-prefix }}/build stage2-package - release_dir=`find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname 'stage2-bins'` - mv $release_dir/${{ needs.prepare.outputs.release-binary-filename }} . - - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 - with: - name: ${{ runner.os }}-${{ runner.arch }}-release-binary - # Due to path differences on Windows when running in bash vs running on node, - # we need to search for files in the current workspace. - path: | - ${{ needs.prepare.outputs.release-binary-filename }} - - # Clean up some build files to reduce size of artifact. - - name: Clean Up Build Directory - shell: bash - run: | - find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname ${{ needs.prepare.outputs.release-binary-filename }} -delete - find ${{ steps.setup-stage.outputs.build-prefix }}/build -iname _CPack_Packages -prune -exec rm -r {} + - - - name: Save Stage - uses: ./workflows-main/.github/workflows/release-binaries-save-stage - with: - build-prefix: ${{ steps.setup-stage.outputs.build-prefix }} - - upload-release-binaries: - name: "Upload Release Binaries" - needs: - - prepare - - build-release-package - if: >- - github.event_name != 'pull_request' && - needs.prepare.outputs.upload == 'true' - runs-on: ubuntu-24.04 - permissions: - contents: write # For release uploads - id-token: write # For artifact attestations - attestations: write # For artifact attestations - - steps: - - name: Checkout Release Scripts - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - sparse-checkout: | - llvm/utils/release/github-upload-release.py - llvm/utils/git/requirements.txt - sparse-checkout-cone-mode: false - - - name: 'Download artifact' - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 - with: - pattern: '*-release-binary' - merge-multiple: true - - - name: Attest Build Provenance - id: provenance - uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0 - with: - subject-path: ${{ needs.prepare.outputs.release-binary-filename }} - - - name: Rename attestation file - run: - mv ${{ steps.provenance.outputs.bundle-path }} ${{ needs.prepare.outputs.release-binary-filename }}.jsonl - - - name: Upload Build Provenance - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3 - with: - name: ${{ needs.prepare.outputs.release-binary-filename }}-attestation - path: ${{ needs.prepare.outputs.release-binary-filename }}.jsonl - - - name: Install Python Requirements - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - - - name: Upload Release - shell: bash - run: | - ./llvm/utils/release/github-upload-release.py \ - --token ${{ github.token }} \ - --release ${{ needs.prepare.outputs.release-version }} \ - upload \ - --files ${{ needs.prepare.outputs.release-binary-filename }}* - - test-release: - name: "Test Release" - needs: - - prepare - - build-release-package - if: >- - github.repository_owner == 'llvm' - runs-on: ${{ needs.prepare.outputs.test-runs-on }} - steps: - - name: Checkout Actions - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - ref: ${{ (github.event_name == 'pull_request' && github.sha) || 'main' }} - sparse-checkout: | - .github/workflows/ - sparse-checkout-cone-mode: false - path: workflows - - name: Setup Stage - id: setup-stage - uses: ./workflows/.github/workflows/release-binaries-setup-stage - with: - previous-artifact: build-release-package - - - name: Run Tests - shell: bash - run: | - ninja -C ${{ steps.setup-stage.outputs.build-prefix }}/build stage2-check-all diff --git a/.github/workflows/release-documentation.yml b/.github/workflows/release-documentation.yml deleted file mode 100644 index 5a0aa063d32ac..0000000000000 --- a/.github/workflows/release-documentation.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: Release Documentation - -permissions: - contents: read - -on: - workflow_dispatch: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload documentation' - required: false - type: boolean - - workflow_call: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload documentation' - required: false - type: boolean - -jobs: - release-documentation: - name: Build and Upload Release Documentation - runs-on: ubuntu-24.04 - env: - upload: ${{ inputs.upload && !contains(inputs.release-version, 'rc') }} - steps: - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Setup Python env - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 - with: - cache: 'pip' - cache-dependency-path: './llvm/docs/requirements.txt' - - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - graphviz \ - python3-github \ - ninja-build \ - texlive-font-utils - pip3 install --user -r ./llvm/docs/requirements.txt - - - name: Build Documentation - env: - GITHUB_TOKEN: ${{ github.token }} - run: | - ./llvm/utils/release/build-docs.sh -release "${{ inputs.release-version }}" -no-doxygen - - - name: Create Release Notes Artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # 4.6.0 - with: - name: release-notes - path: docs-build/html-export/ - - - name: Clone www-releases - if: env.upload - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - repository: ${{ github.repository_owner }}/www-releases - ref: main - fetch-depth: 0 - path: www-releases - persist-credentials: false - - - name: Upload Release Notes - if: env.upload - env: - GH_TOKEN: ${{ secrets.WWW_RELEASES_TOKEN }} - run: | - mkdir -p www-releases/${{ inputs.release-version }} - mv ./docs-build/html-export/* www-releases/${{ inputs.release-version }} - cd www-releases - git checkout -b ${{ inputs.release-version }} - git add ${{ inputs.release-version }} - git config user.email "llvmbot@llvm.org" - git config user.name "llvmbot" - git commit -a -m "Add ${{ inputs.release-version }} documentation" - git push --force "https://$GH_TOKEN@github.com/llvmbot/www-releases.git" HEAD:refs/heads/${{ inputs.release-version }} - gh pr create -f -B main -H ${{ inputs.release-version }} -R llvmbot/www-releases diff --git a/.github/workflows/release-doxygen.yml b/.github/workflows/release-doxygen.yml deleted file mode 100644 index d47c4337c07b2..0000000000000 --- a/.github/workflows/release-doxygen.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Release Doxygen - -permissions: - contents: read - -on: - workflow_dispatch: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload documentation' - required: false - type: boolean - - workflow_call: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - upload: - description: 'Upload documentation' - required: false - type: boolean - secrets: - RELEASE_TASKS_USER_TOKEN: - description: "Secret used to check user permissions." - required: false - -jobs: - release-doxygen: - name: Build and Upload Release Doxygen - runs-on: ubuntu-24.04 - permissions: - contents: write - env: - upload: ${{ inputs.upload && !contains(inputs.release-version, 'rc') }} - steps: - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Setup Python env - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 - with: - cache: 'pip' - cache-dependency-path: './llvm/docs/requirements.txt' - - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - doxygen \ - graphviz \ - python3-github \ - ninja-build \ - texlive-font-utils - pip3 install --user -r ./llvm/docs/requirements.txt - - - name: Build Doxygen - run: | - ./llvm/utils/release/build-docs.sh -release "${{ inputs.release-version }}" -no-sphinx - - - name: Upload Doxygen - if: env.upload - env: - GITHUB_TOKEN: ${{ github.token }} - USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - run: | - ./llvm/utils/release/github-upload-release.py --token "$GITHUB_TOKEN" --release "${{ inputs.release-version }}" --user "${{ github.actor }}" --user-token "$USER_TOKEN" upload --files ./*doxygen*.tar.xz diff --git a/.github/workflows/release-lit.yml b/.github/workflows/release-lit.yml deleted file mode 100644 index 9adeffb74d52a..0000000000000 --- a/.github/workflows/release-lit.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Release Lit - -permissions: - contents: read - -on: - workflow_dispatch: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - - workflow_call: - inputs: - release-version: - description: 'Release Version' - required: true - type: string - secrets: - RELEASE_TASKS_USER_TOKEN: - description: "Secret used to check user permissions." - required: false - -jobs: - release-lit: - name: Release Lit - runs-on: ubuntu-24.04 - steps: - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: "llvmorg-${{ inputs.release-version }}" - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y python3-setuptools python3-psutil python3-github - - - name: Check Permissions - env: - GITHUB_TOKEN: ${{ github.token }} - USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - run: | - ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} --user-token "$USER_TOKEN" check-permissions - - - name: Setup Cpp - uses: aminya/setup-cpp@17c11551771948abc5752bbf3183482567c7caf0 # v1.1.1 - with: - compiler: llvm-16.0.6 - cmake: true - ninja: true - - - name: Test lit - run: | - mkdir build && cd build - export FILECHECK_OPTS='-dump-input-filter=all -vv -color' - cmake ../llvm -DCMAKE_BUILD_TYPE=Release -G Ninja - ninja -v -j $(nproc) check-lit - - - name: Package lit - run: | - cd llvm/utils/lit - # Remove 'dev' suffix from lit version. - sed -i 's/ + "dev"//g' lit/__init__.py - python3 setup.py sdist bdist_wheel - - - name: Upload lit to test.pypi.org - uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 - with: - password: ${{ secrets.LLVM_LIT_TEST_PYPI_API_TOKEN }} - repository-url: https://test.pypi.org/legacy/ - packages-dir: llvm/utils/lit/dist/ - - - name: Upload lit to pypi.org - uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 - with: - password: ${{ secrets.LLVM_LIT_PYPI_API_TOKEN }} - packages-dir: llvm/utils/lit/dist/ diff --git a/.github/workflows/release-sources.yml b/.github/workflows/release-sources.yml deleted file mode 100644 index 99438918b56f0..0000000000000 --- a/.github/workflows/release-sources.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: Release Sources - -permissions: - contents: read - -on: - workflow_dispatch: - inputs: - release-version: - description: Release Version - required: true - type: string - workflow_call: - inputs: - release-version: - description: Release Version - required: true - type: string - secrets: - RELEASE_TASKS_USER_TOKEN: - description: "Secret used to check user permissions." - required: false - # Run on pull_requests for testing purposes. - pull_request: - paths: - - '.github/workflows/release-sources.yml' - types: - - opened - - synchronize - - reopened - # When a PR is closed, we still start this workflow, but then skip - # all the jobs, which makes it effectively a no-op. The reason to - # do this is that it allows us to take advantage of concurrency groups - # to cancel in progress CI jobs whenever the PR is closed. - - closed - -concurrency: - group: ${{ github.workflow }}-${{ inputs.release-version || github.event.pull_request.number }} - cancel-in-progress: True - -jobs: - inputs: - name: Collect Job Inputs - if: >- - github.repository_owner == 'llvm' && - github.event.action != 'closed' - outputs: - ref: ${{ steps.inputs.outputs.ref }} - export-args: ${{ steps.inputs.outputs.export-args }} - runs-on: ubuntu-24.04 - steps: - - id: inputs - run: | - ref=${{ (inputs.release-version && format('llvmorg-{0}', inputs.release-version)) || github.sha }} - if [ -n "${{ inputs.release-version }}" ]; then - export_args="-release ${{ inputs.release-version }} -final" - else - export_args="-git-ref ${{ github.sha }}" - fi - echo "ref=$ref" >> $GITHUB_OUTPUT - echo "export-args=$export_args" >> $GITHUB_OUTPUT - - release-sources: - name: Package Release Sources - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - needs: - - inputs - permissions: - id-token: write - attestations: write - steps: - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - ref: ${{ needs.inputs.outputs.ref }} - fetch-tags: true - - name: Install Dependencies - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - - - name: Check Permissions - if: github.event_name != 'pull_request' - env: - GITHUB_TOKEN: ${{ github.token }} - USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - run: | - ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} --user-token "$USER_TOKEN" check-permissions - - name: Create Tarballs - run: | - ./llvm/utils/release/export.sh ${{ needs.inputs.outputs.export-args }} - - name: Attest Build Provenance - if: github.event_name != 'pull_request' - id: provenance - uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0 - with: - subject-path: "*.xz" - - if: github.event_name != 'pull_request' - run: | - mv ${{ steps.provenance.outputs.bundle-path }} . - - name: Create Tarball Artifacts - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 #v4.3.3 - with: - path: | - *.xz - attestation.jsonl - - diff --git a/.github/workflows/release-tasks.yml b/.github/workflows/release-tasks.yml deleted file mode 100644 index d55098345d89e..0000000000000 --- a/.github/workflows/release-tasks.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: Release Task - -permissions: - contents: read - -on: - push: - tags: - # The regex support here is limited, so just match everything that starts with llvmorg- and filter later. - - 'llvmorg-*' - -jobs: - validate-tag: - name: Validate Tag - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - outputs: - release-version: ${{ steps.validate-tag.outputs.release-version }} - steps: - - name: Validate Tag - id: validate-tag - run: | - echo "${{ github.ref_name }}" | grep -e '^llvmorg-[0-9]\+\.[0-9]\+\.[0-9]\+\(-rc[0-9]\+\)\?$' - release_version=$(echo "${{ github.ref_name }}" | sed 's/llvmorg-//g') - echo "release-version=$release_version" >> "$GITHUB_OUTPUT" - - release-create: - name: Create a New Release - runs-on: ubuntu-24.04 - permissions: - contents: write # For creating the release. - needs: validate-tag - - steps: - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install python3-github - - - name: Checkout LLVM - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Create Release - env: - GITHUB_TOKEN: ${{ github.token }} - USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - run: | - ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --release ${{ needs.validate-tag.outputs.release-version }} --user ${{ github.actor }} --user-token "$USER_TOKEN" create - release-documentation: - name: Build and Upload Release Documentation - needs: - - validate-tag - uses: ./.github/workflows/release-documentation.yml - with: - release-version: ${{ needs.validate-tag.outputs.release-version }} - upload: true - - release-doxygen: - name: Build and Upload Release Doxygen - permissions: - contents: write - needs: - - validate-tag - - release-create - uses: ./.github/workflows/release-doxygen.yml - with: - release-version: ${{ needs.validate-tag.outputs.release-version }} - upload: true - # Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use. - secrets: - RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - - release-lit: - name: Release Lit - needs: validate-tag - uses: ./.github/workflows/release-lit.yml - with: - release-version: ${{ needs.validate-tag.outputs.release-version }} - # Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use. - secrets: - RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - - release-binaries: - name: Build Release Binaries - permissions: - contents: write - id-token: write - attestations: write - needs: - - validate-tag - - release-create - uses: ./.github/workflows/release-binaries-all.yml - with: - release-version: ${{ needs.validate-tag.outputs.release-version }} - upload: true - # Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use. - secrets: - RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} - - release-sources: - name: Package Release Sources - permissions: - contents: read - id-token: write - attestations: write - needs: - - validate-tag - uses: ./.github/workflows/release-sources.yml - with: - release-version: ${{ needs.validate-tag.outputs.release-version }} - # Called workflows don't have access to secrets by default, so we need to explicitly pass secrets that we use. - secrets: - RELEASE_TASKS_USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml deleted file mode 100644 index 6cc80fb316c67..0000000000000 --- a/.github/workflows/scorecard.yml +++ /dev/null @@ -1,62 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. They are provided -# by a third-party and are governed by separate terms of service, privacy -# policy, and support documentation. - -# Check current LLVM-Project results here: https://securityscorecards.dev/viewer/?uri=github.com/llvm/llvm-project - -name: Scorecard supply-chain security -on: - # For Branch-Protection check. Only the default branch is supported. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection - branch_protection_rule: - # To guarantee Maintained check is occasionally updated. See - # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained - schedule: - - cron: '38 20 * * *' - -# Declare default permissions as read only. -permissions: - contents: read - -jobs: - analysis: - name: Scorecard analysis - runs-on: ubuntu-24.04 - if: github.repository == 'llvm/llvm-project' - permissions: - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Needed to publish results and get a badge (see publish_results below). - id-token: write - - steps: - - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 - with: - results_file: results.sarif - results_format: sarif - - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. - - name: "Upload artifact" - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard. - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@80f993039571a6de66594ecaa432875a6942e8e0 # v2.20.6 - with: - sarif_file: results.sarif diff --git a/.github/workflows/set-release-binary-outputs.sh b/.github/workflows/set-release-binary-outputs.sh deleted file mode 100644 index 14d0798364e91..0000000000000 --- a/.github/workflows/set-release-binary-outputs.sh +++ /dev/null @@ -1,34 +0,0 @@ -# Usage: set-release-binary-outputs.sh - -set -e - -if [ -z "$GITHUB_OUTPUT" ]; then - export GITHUB_OUTPUT=`mktemp` - echo "Warning: Environment variable GITHUB_OUTPUT is not set." - echo "Writing output variables to $GITHUB_OUTPUT" -fi - -tag=$1 -upload=$2 - -if echo $tag | grep -e '^[0-9a-f]\+$'; then - # This is a plain commit. - # TODO: Don't hardcode this. - release_version="18" - upload='false' - ref="$tag" - -else - - pattern='^llvmorg-[0-9]\+\.[0-9]\+\.[0-9]\+\(-rc[0-9]\+\)\?$' - echo "$tag" | grep -e $pattern - if [ $? != 0 ]; then - echo "ERROR: Tag '$tag' doesn't match pattern: $pattern" - exit 1 - fi - release_version=`echo "$tag" | sed 's/llvmorg-//g'` - release=`echo "$release_version" | sed 's/-.*//g'` -fi -echo "release-version=$release_version" >> $GITHUB_OUTPUT -echo "upload=$upload" >> $GITHUB_OUTPUT -echo "ref=$tag" >> $GITHUB_OUTPUT diff --git a/.github/workflows/spirv-tests.yml b/.github/workflows/spirv-tests.yml deleted file mode 100644 index f15ca1cb64ba5..0000000000000 --- a/.github/workflows/spirv-tests.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: SPIR-V Tests - -permissions: - contents: read - -on: - workflow_dispatch: - pull_request: - paths: - - 'llvm/lib/Target/SPIRV/**' - - 'llvm/test/CodeGen/SPIRV/**' - - '.github/workflows/spirv-tests.yml' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_spirv: - if: github.repository_owner == 'llvm' - name: Test SPIR-V - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-llvm-codegen-spirv - projects: - extra_cmake_args: '-DLLVM_TARGETS_TO_BUILD="SPIRV" -DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON' - os_list: '["ubuntu-24.04"]' diff --git a/.github/workflows/unprivileged-download-artifact/action.yml b/.github/workflows/unprivileged-download-artifact/action.yml deleted file mode 100644 index 9d8fb59a67c0e..0000000000000 --- a/.github/workflows/unprivileged-download-artifact/action.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: Unprivileged Download Artifact -description: >- - Download artifacts from another workflow run without using an access token. -inputs: - run-id: - description: >- - The run-id for the workflow run that you want to download the artifact - from. If ommitted it will download the most recently created artifact - from the repo with the artifact-name. - required: false - artifact-name: - desciption: The name of the artifact to download. - required: true - - -outputs: - filename: - description: >- - The filename of the downloaded artifact or the empty string if the - artifact was not found. - value: ${{ steps.download-artifact.outputs.filename }} - artifact-id: - description: "The id of the artifact being downloaded." - value: ${{ steps.artifact-url.outputs.id }} - - -runs: - using: "composite" - steps: - - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 - id: artifact-url - with: - script: | - var response; - if (!"${{ inputs.run-id }}") { - response = await github.rest.actions.listArtifactsForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - name: "${{ inputs.artifact-name }}" - }) - } else { - response = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: "${{ inputs.run-id }}", - name: "${{ inputs.artifact-name }}" - }) - } - - console.log(response) - - for (artifact of response.data.artifacts) { - console.log(artifact); - } - - if (response.data.artifacts.length == 0) { - console.log("Could not find artifact ${{ inputs.artifact-name }} for workflow run ${{ inputs.run-id }}") - return; - } - - const url_response = await github.rest.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: response.data.artifacts[0].id, - archive_format: "zip" - }) - - core.setOutput("url", url_response.url); - core.setOutput("id", response.data.artifacts[0].id); - - - shell: bash - if: steps.artifact-url.outputs.url != '' - id: download-artifact - run: | - curl -L -o ${{ inputs.artifact-name }}.zip "${{ steps.artifact-url.outputs.url }}" - echo "filename=${{ inputs.artifact-name }}.zip" >> $GITHUB_OUTPUT - - - shell: bash - if: steps.download-artifact.outputs.filename != '' - run: | - unzip ${{ steps.download-artifact.outputs.filename }} diff --git a/.github/workflows/version-check.py b/.github/workflows/version-check.py deleted file mode 100755 index f75fd50300881..0000000000000 --- a/.github/workflows/version-check.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 - -from git import Repo -import re -import sys - - -def get_version_from_tag(tag): - m = re.match("llvmorg-([0-9]+)\.([0-9]+)\.([0-9]+)(-rc[0-9]+)?$", tag) - if m: - if m.lastindex == 4: - # We have an rc tag. - return m.group(1, 2, 3) - # We have a final release tag. - return (m.group(1), m.group(2), str(int(m.group(3)) + 1)) - - m = re.match("llvmorg-([0-9]+)-init", tag) - if m: - return (m.group(1), "1", "0") - - raise Exception(f"error: Tag is not valid: {tag}") - - -version = sys.argv[1] - -repo = Repo() - -tag = repo.git.describe(tags=True, abbrev=0) -expected_version = ".".join(get_version_from_tag(tag)) - -if version != expected_version: - print("error: Expected version", expected_version, "but found version", version) - sys.exit(1) - -print("Versions match:", version, expected_version) -sys.exit(0) diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml deleted file mode 100644 index a0a598094376f..0000000000000 --- a/.github/workflows/version-check.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: LLVM Project Version Check - -on: - push: - branches: - - 'release/**' - pull_request: - branches: - - 'release/**' - -permissions: - contents: read - -jobs: - version_check: - if: github.repository_owner == 'llvm' - runs-on: ubuntu-24.04 - steps: - - name: Fetch LLVM sources - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - fetch-depth: 0 - - - name: Install dependencies - run: | - pip install --require-hashes -r ./llvm/utils/git/requirements.txt - - - name: Version Check - run: | - version=$(grep -o 'LLVM_VERSION_\(MAJOR\|MINOR\|PATCH\) [0-9]\+' cmake/Modules/LLVMVersion.cmake | cut -d ' ' -f 2 | tr "\n" "." | sed 's/.$//g') - .github/workflows/version-check.py "$version" diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index a703009e2b467..e83af299bbd18 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -81,7 +81,7 @@ CodeAction toCodeAction(const ClangdServer::CodeActionResult::Rename &R, const URIForFile &File) { CodeAction CA; CA.title = R.FixMessage; - CA.kind = std::string(CodeAction::REFACTOR_KIND); + CA.kind = std::string(CodeAction::QUICKFIX_KIND); CA.command.emplace(); CA.command->title = R.FixMessage; CA.command->command = std::string(ApplyRenameCommand); diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index 9e00dbc9dc90a..c5488c2378a1e 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -315,7 +315,7 @@ struct Fragment { /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and /// AngledHeaders), system headers use <> and non-system headers use "". /// These can match any suffix of the header file in question. - /// Matching is performed against the header text, not its absolute path + /// Matching is performed against the absolute path of the header /// within the project. std::vector> QuotedHeaders; /// List of regexes for headers that should always be included with a @@ -323,7 +323,7 @@ struct Fragment { /// AngledHeaders (i.e. a header matches a regex in both QuotedHeaders and /// AngledHeaders), system headers use <> and non-system headers use "". /// These can match any suffix of the header file in question. - /// Matching is performed against the header text, not its absolute path + /// Matching is performed against the absolute path of the header /// within the project. std::vector> AngledHeaders; }; diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 7c0eb9651feaa..c6afd0bc07cbd 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -833,6 +833,10 @@ bool OverlayCDB::setCompileCommand(PathRef File, std::unique_ptr OverlayCDB::getProjectModules(PathRef File) const { auto MDB = DelegatingCDB::getProjectModules(File); + if (!MDB) { + log("Failed to get compilation Database for {0}", File); + return {}; + } MDB->setCommandMangler([&Mangler = Mangler](tooling::CompileCommand &Command, PathRef CommandPath) { Mangler(Command, CommandPath); diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 87fd261b906e6..b9d67cc6a1602 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -304,16 +304,17 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, // FIXME: should we allow (some limited number of) "../header.h"? if (llvm::sys::path::is_absolute(Suggested)) return std::nullopt; + auto HeaderPath = llvm::sys::path::convert_to_slash(InsertedHeader.File); bool IsAngled = false; for (auto &Filter : AngledHeaders) { - if (Filter(Suggested)) { + if (Filter(HeaderPath)) { IsAngled = true; break; } } bool IsQuoted = false; for (auto &Filter : QuotedHeaders) { - if (Filter(Suggested)) { + if (Filter(HeaderPath)) { IsQuoted = true; break; } @@ -324,7 +325,7 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, if (IsAngled && IsQuoted) { elog("Header '{0}' matches both quoted and angled regexes, default will " "be used.", - Suggested); + HeaderPath); } IsAngled = IsAngledByDefault; } diff --git a/clang-tools-extra/clangd/test/modules_no_cdb.test b/clang-tools-extra/clangd/test/modules_no_cdb.test new file mode 100644 index 0000000000000..8f92be2c7b3f3 --- /dev/null +++ b/clang-tools-extra/clangd/test/modules_no_cdb.test @@ -0,0 +1,66 @@ +# A smoke test to check that clangd works without compilation database +# +# Windows have different escaping modes. +# FIXME: We should add one for windows. +# UNSUPPORTED: system-windows +# +# RUN: rm -fr %t +# RUN: mkdir -p %t +# RUN: split-file %s %t +# +# RUN: sed -e "s|DIR|%/t|g" %t/definition.jsonrpc.tmpl > %t/definition.jsonrpc +# +# RUN: clangd -experimental-modules-support -lit-test < %t/definition.jsonrpc \ +# RUN: | FileCheck -strict-whitespace %t/definition.jsonrpc + +#--- A.h +void printA(); + +#--- Use.cpp +#include "A.h" +void foo() { + print +} + +#--- definition.jsonrpc.tmpl +{ + "jsonrpc": "2.0", + "id": 0, + "method": "initialize", + "params": { + "processId": 123, + "rootPath": "clangd", + "capabilities": { + "textDocument": { + "completion": { + "completionItem": { + "snippetSupport": true + } + } + } + }, + "trace": "off" + } +} +--- +{ + "jsonrpc": "2.0", + "method": "textDocument/didOpen", + "params": { + "textDocument": { + "uri": "file://DIR/Use.cpp", + "languageId": "cpp", + "version": 1, + "text": "#include \"A.h\"\nvoid foo() {\n print\n}\n" + } + } +} + +# CHECK: "message"{{.*}}printA{{.*}}(fix available) + +--- +{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file://DIR/Use.cpp"},"context":{"triggerKind":1},"position":{"line":2,"character":6}}} +--- +{"jsonrpc":"2.0","id":2,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp index 2c7f50d8c9e4c..95bf5e54fc792 100644 --- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp @@ -235,7 +235,8 @@ TEST_F(LSPTest, ClangTidyRename) { .takeValue() .getAsArray())[0]; - ASSERT_EQ((*RenameCommand.getAsObject())["title"], "change 'foo' to 'Foo'"); + ASSERT_EQ((*RenameCommand.getAsObject())["title"], + "Apply fix: change 'foo' to 'Foo'"); Client.expectServerCall("workspace/applyEdit"); Client.call("workspace/executeCommand", RenameCommand); diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index b7c64c7a06745..3c107504e6253 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -938,7 +938,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) { { Config C; C.Style.AngledHeaders.push_back( - [](auto header) { return header == "bar.h"; }); + [](auto header) { return header.contains("bar.h"); }); WithContextValue WithCfg(Config::Key, std::move(C)); Results = completions(TU, Test.point(), {Sym}); EXPECT_THAT(Results.Completions, @@ -947,7 +947,7 @@ TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) { { Config C; C.Style.QuotedHeaders.push_back( - [](auto header) { return header == "bar.h"; }); + [](auto header) { return header.contains("bar.h"); }); WithContextValue WithCfg(Config::Key, std::move(C)); Results = completions(TU, Test.point(), {Sym}); EXPECT_THAT(Results.Completions, diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp index 751383e3b4650..440582e14239a 100644 --- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp +++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp @@ -344,6 +344,17 @@ TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketed) { EXPECT_EQ(calculate(BarHeader), ""); } +TEST_F(HeadersTest, ShortenIncludesInSearchPathBracketedFilterByFullPath) { + // The filter receives the full path of the header, so it is able to filter by + // the parent directory, even if it is part of the include search path + AngledHeaders.push_back([](auto Path) { + llvm::Regex Pattern("sub/.*"); + return Pattern.match(Path); + }); + std::string BarHeader = testPath("sub/bar.h"); + EXPECT_EQ(calculate(BarHeader), ""); +} + TEST_F(HeadersTest, ShortenedIncludeNotInSearchPath) { std::string BarHeader = llvm::sys::path::convert_to_slash(testPath("sub-2/bar.h")); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index cf97ab7082472..b7aa55a2e20d0 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -46,14 +46,18 @@ Major New Features Improvements to clangd ---------------------- -Inlay hints -^^^^^^^^^^^ +Language feature support +^^^^^^^^^^^^^^^^^^^^^^^^ -Diagnostics -^^^^^^^^^^^ +- Performance improvements and bugfixes to C++20 Modules support +- Improved support for C++23 "deducing this" +- Improvements to objective-c++ support -Semantic Highlighting -^^^^^^^^^^^^^^^^^^^^^ +New Language Server Protocol features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Added support for `textDocument/rangesFormatting` +- Added support for `positionEncoding` Compile flags ^^^^^^^^^^^^^ @@ -64,24 +68,58 @@ Compile flags Hover ^^^^^ +- Fixed a bug that would sometimes prevent documentation comments of standard library functions + from being shown + Code completion ^^^^^^^^^^^^^^^ -Code actions -^^^^^^^^^^^^ - -Signature help -^^^^^^^^^^^^^^ +- Added `HeaderInsertion` config option to control whether code completion inserts a missing + header needed for the symbol being completed. This is equivalent to the `--header-insertion` + command-line option. +- Added a `CodePatterns` config option to control whether code completion should offer code + patterns as completions in addition to symbols. Cross-references ^^^^^^^^^^^^^^^^ -Objective-C +- References to symbols are now collected in array designators +- Find-references now works for operators new and delete +- Improvements to code navigation in templated code + +Call hierarchy +^^^^^^^^^^^^^^ + +- Call hierarchy now works with the remote index +- Fixed a bug where call hierarchy could sometimes return bogus results + +Inlay hints ^^^^^^^^^^^ +- Parameter hint forwarding now works for variadic forwarding functions declared in header files +- Improved presentation of block-end hints + +Code actions +^^^^^^^^^^^^ + +- Improved the rename refactor's name collision checking logic + +Clang-tidy integration +^^^^^^^^^^^^^^^^^^^^^^ + +- Disabled the cppcoreguidelines-macro-to-enum checker which is incompatible with clangd + +Include-cleaner integration +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Clangd now respects the `AngledHeaders` and `QuotedHeaders` config options for headers + inserted to resolve include-cleaner diagnostics + Miscellaneous ^^^^^^^^^^^^^ +- Various crash fixes and other stability improvements + Improvements to clang-doc ------------------------- diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h index 2888e25226755..057b92c147047 100644 --- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h +++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h @@ -136,7 +136,7 @@ struct Header { } StringRef verbatim() const { return std::get(Storage); } - /// For phiscal files, either absolute path or path relative to the execution + /// For physical files, either absolute path or path relative to the execution /// root. Otherwise just the spelling without surrounding quotes/brackets. llvm::StringRef resolvedPath() const; diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index f4c309f1b35c0..1bb73599970c1 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -536,6 +536,7 @@ if( CLANG_INCLUDE_TESTS ) clang_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/test/Unit/lit.site.cfg ) add_subdirectory(test) + add_subdirectory(bindings/python/tests) if(CLANG_BUILT_STANDALONE) umbrella_lit_testsuite_end(check-all) diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 824674309d262..5ce7b5781bcb4 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -3853,6 +3853,8 @@ def cursor(self): cursor._tu = self._tu conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor)) + if cursor.is_null(): + return None return cursor diff --git a/clang/bindings/python/tests/CMakeLists.txt b/clang/bindings/python/tests/CMakeLists.txt new file mode 100644 index 0000000000000..a0ddabc21bb41 --- /dev/null +++ b/clang/bindings/python/tests/CMakeLists.txt @@ -0,0 +1,66 @@ +# Test target to run Python test suite from main build. + +# Avoid configurations including '-include' from interfering with +# our tests by setting CLANG_NO_DEFAULT_CONFIG. +add_custom_target(check-clang-python + COMMAND ${CMAKE_COMMAND} -E env + CLANG_NO_DEFAULT_CONFIG=1 + CLANG_LIBRARY_PATH=$ + "${Python3_EXECUTABLE}" -m unittest discover + DEPENDS libclang + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..) + +set(RUN_PYTHON_TESTS TRUE) +set_target_properties(check-clang-python PROPERTIES FOLDER "Clang/Tests") + +# Tests require libclang.so which is only built with LLVM_ENABLE_PIC=ON +if(NOT LLVM_ENABLE_PIC) + set(RUN_PYTHON_TESTS FALSE) +endif() + +# Do not try to run if libclang was built with sanitizers because +# the sanitizer library will likely be loaded too late to perform +# interception and will then fail. +# We could use LD_PRELOAD/DYLD_INSERT_LIBRARIES but this isn't +# portable so its easier just to not run the tests when building +# with ASan. +if(NOT LLVM_USE_SANITIZER STREQUAL "") + set(RUN_PYTHON_TESTS FALSE) +endif() + +# Tests fail on Windows, and need someone knowledgeable to fix. +# It's not clear whether it's a test or a valid binding problem. +if(WIN32) + set(RUN_PYTHON_TESTS FALSE) +endif() + +# The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628. +if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") + set(RUN_PYTHON_TESTS FALSE) +endif() + +# AArch64, Hexagon, and Sparc have known test failures that need to be +# addressed. +# SystemZ has broken Python/FFI interface: +# https://reviews.llvm.org/D52840#1265716 +if(${LLVM_NATIVE_ARCH} MATCHES "^(AArch64|Hexagon|Sparc|SystemZ)$") + set(RUN_PYTHON_TESTS FALSE) +endif() + +# Tests will fail if cross-compiling for a different target, as tests will try +# to use the host Python3_EXECUTABLE and make FFI calls to functions in target +# libraries. +if(CMAKE_CROSSCOMPILING) + # FIXME: Consider a solution that allows better control over these tests in + # a crosscompiling scenario. e.g. registering them with lit to allow them to + # be explicitly skipped via appropriate LIT_ARGS, or adding a mechanism to + # allow specifying a python interpreter compiled for the target that could + # be executed using qemu-user. + message(WARNING "check-clang-python not added to check-all as these tests fail in a cross-build setup") + set(RUN_PYTHON_TESTS FALSE) +endif() + +if(RUN_PYTHON_TESTS) + set_property(GLOBAL APPEND PROPERTY + LLVM_ALL_ADDITIONAL_TEST_TARGETS check-clang-python) +endif() diff --git a/clang/test/bindings/python/tests/__init__.py b/clang/bindings/python/tests/__init__.py similarity index 100% rename from clang/test/bindings/python/tests/__init__.py rename to clang/bindings/python/tests/__init__.py diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/a.inc b/clang/bindings/python/tests/cindex/INPUTS/a.inc similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/a.inc rename to clang/bindings/python/tests/cindex/INPUTS/a.inc diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/b.inc b/clang/bindings/python/tests/cindex/INPUTS/b.inc similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/b.inc rename to clang/bindings/python/tests/cindex/INPUTS/b.inc diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/compile_commands.json b/clang/bindings/python/tests/cindex/INPUTS/compile_commands.json similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/compile_commands.json rename to clang/bindings/python/tests/cindex/INPUTS/compile_commands.json diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/header1.h b/clang/bindings/python/tests/cindex/INPUTS/header1.h similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/header1.h rename to clang/bindings/python/tests/cindex/INPUTS/header1.h diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/header2.h b/clang/bindings/python/tests/cindex/INPUTS/header2.h similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/header2.h rename to clang/bindings/python/tests/cindex/INPUTS/header2.h diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/header3.h b/clang/bindings/python/tests/cindex/INPUTS/header3.h similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/header3.h rename to clang/bindings/python/tests/cindex/INPUTS/header3.h diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/hello.cpp b/clang/bindings/python/tests/cindex/INPUTS/hello.cpp similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/hello.cpp rename to clang/bindings/python/tests/cindex/INPUTS/hello.cpp diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/include.cpp b/clang/bindings/python/tests/cindex/INPUTS/include.cpp similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/include.cpp rename to clang/bindings/python/tests/cindex/INPUTS/include.cpp diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/parse_arguments.c b/clang/bindings/python/tests/cindex/INPUTS/parse_arguments.c similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/parse_arguments.c rename to clang/bindings/python/tests/cindex/INPUTS/parse_arguments.c diff --git a/clang/test/bindings/python/tests/cindex/INPUTS/testfile.c b/clang/bindings/python/tests/cindex/INPUTS/testfile.c similarity index 100% rename from clang/test/bindings/python/tests/cindex/INPUTS/testfile.c rename to clang/bindings/python/tests/cindex/INPUTS/testfile.c diff --git a/clang/test/bindings/python/tests/cindex/__init__.py b/clang/bindings/python/tests/cindex/__init__.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/__init__.py rename to clang/bindings/python/tests/cindex/__init__.py diff --git a/clang/test/bindings/python/tests/cindex/test_access_specifiers.py b/clang/bindings/python/tests/cindex/test_access_specifiers.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_access_specifiers.py rename to clang/bindings/python/tests/cindex/test_access_specifiers.py diff --git a/clang/test/bindings/python/tests/cindex/test_cdb.py b/clang/bindings/python/tests/cindex/test_cdb.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_cdb.py rename to clang/bindings/python/tests/cindex/test_cdb.py diff --git a/clang/test/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_code_completion.py rename to clang/bindings/python/tests/cindex/test_code_completion.py diff --git a/clang/test/bindings/python/tests/cindex/test_comment.py b/clang/bindings/python/tests/cindex/test_comment.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_comment.py rename to clang/bindings/python/tests/cindex/test_comment.py diff --git a/clang/test/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_cursor.py rename to clang/bindings/python/tests/cindex/test_cursor.py diff --git a/clang/test/bindings/python/tests/cindex/test_cursor_kind.py b/clang/bindings/python/tests/cindex/test_cursor_kind.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_cursor_kind.py rename to clang/bindings/python/tests/cindex/test_cursor_kind.py diff --git a/clang/test/bindings/python/tests/cindex/test_diagnostics.py b/clang/bindings/python/tests/cindex/test_diagnostics.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_diagnostics.py rename to clang/bindings/python/tests/cindex/test_diagnostics.py diff --git a/clang/test/bindings/python/tests/cindex/test_enums.py b/clang/bindings/python/tests/cindex/test_enums.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_enums.py rename to clang/bindings/python/tests/cindex/test_enums.py diff --git a/clang/test/bindings/python/tests/cindex/test_exception_specification_kind.py b/clang/bindings/python/tests/cindex/test_exception_specification_kind.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_exception_specification_kind.py rename to clang/bindings/python/tests/cindex/test_exception_specification_kind.py diff --git a/clang/test/bindings/python/tests/cindex/test_file.py b/clang/bindings/python/tests/cindex/test_file.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_file.py rename to clang/bindings/python/tests/cindex/test_file.py diff --git a/clang/test/bindings/python/tests/cindex/test_index.py b/clang/bindings/python/tests/cindex/test_index.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_index.py rename to clang/bindings/python/tests/cindex/test_index.py diff --git a/clang/test/bindings/python/tests/cindex/test_lib.py b/clang/bindings/python/tests/cindex/test_lib.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_lib.py rename to clang/bindings/python/tests/cindex/test_lib.py diff --git a/clang/test/bindings/python/tests/cindex/test_linkage.py b/clang/bindings/python/tests/cindex/test_linkage.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_linkage.py rename to clang/bindings/python/tests/cindex/test_linkage.py diff --git a/clang/test/bindings/python/tests/cindex/test_location.py b/clang/bindings/python/tests/cindex/test_location.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_location.py rename to clang/bindings/python/tests/cindex/test_location.py diff --git a/clang/test/bindings/python/tests/cindex/test_rewrite.py b/clang/bindings/python/tests/cindex/test_rewrite.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_rewrite.py rename to clang/bindings/python/tests/cindex/test_rewrite.py diff --git a/clang/test/bindings/python/tests/cindex/test_source_range.py b/clang/bindings/python/tests/cindex/test_source_range.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_source_range.py rename to clang/bindings/python/tests/cindex/test_source_range.py diff --git a/clang/test/bindings/python/tests/cindex/test_tls_kind.py b/clang/bindings/python/tests/cindex/test_tls_kind.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_tls_kind.py rename to clang/bindings/python/tests/cindex/test_tls_kind.py diff --git a/clang/test/bindings/python/tests/cindex/test_token_kind.py b/clang/bindings/python/tests/cindex/test_token_kind.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_token_kind.py rename to clang/bindings/python/tests/cindex/test_token_kind.py diff --git a/clang/test/bindings/python/tests/cindex/test_tokens.py b/clang/bindings/python/tests/cindex/test_tokens.py similarity index 86% rename from clang/test/bindings/python/tests/cindex/test_tokens.py rename to clang/bindings/python/tests/cindex/test_tokens.py index b6c1fc8b83600..6658579c63835 100644 --- a/clang/test/bindings/python/tests/cindex/test_tokens.py +++ b/clang/bindings/python/tests/cindex/test_tokens.py @@ -53,3 +53,9 @@ def test_token_extent(self): self.assertEqual(extent.start.offset, 4) self.assertEqual(extent.end.offset, 7) + + def test_null_cursor(self): + """Ensure that the cursor property converts null cursors to None""" + tu = get_tu("int i = 5;") + tokens = list(tu.get_tokens(extent=tu.cursor.extent)) + self.assertEqual(tokens[-1].cursor, None) diff --git a/clang/test/bindings/python/tests/cindex/test_translation_unit.py b/clang/bindings/python/tests/cindex/test_translation_unit.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_translation_unit.py rename to clang/bindings/python/tests/cindex/test_translation_unit.py diff --git a/clang/test/bindings/python/tests/cindex/test_type.py b/clang/bindings/python/tests/cindex/test_type.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/test_type.py rename to clang/bindings/python/tests/cindex/test_type.py diff --git a/clang/test/bindings/python/tests/cindex/util.py b/clang/bindings/python/tests/cindex/util.py similarity index 100% rename from clang/test/bindings/python/tests/cindex/util.py rename to clang/bindings/python/tests/cindex/util.py diff --git a/clang/cmake/caches/PGO.cmake b/clang/cmake/caches/PGO.cmake index 15bc755d110d1..d6471160037c1 100644 --- a/clang/cmake/caches/PGO.cmake +++ b/clang/cmake/caches/PGO.cmake @@ -5,7 +5,7 @@ set(LLVM_ENABLE_PROJECTS "clang;lld" CACHE STRING "") set(LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "") set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "") -set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED ON CACHE BOOL "") +set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED IR CACHE BOOL "") set(CLANG_BOOTSTRAP_TARGETS generate-profdata stage2 diff --git a/clang/cmake/caches/Release.cmake b/clang/cmake/caches/Release.cmake index fb12dfcdcb5a5..9f7e906241106 100644 --- a/clang/cmake/caches/Release.cmake +++ b/clang/cmake/caches/Release.cmake @@ -44,6 +44,19 @@ set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "") set(LLVM_RELEASE_ENABLE_PGO ON CACHE BOOL "") set(LLVM_RELEASE_ENABLE_RUNTIMES ${DEFAULT_RUNTIMES} CACHE STRING "") set(LLVM_RELEASE_ENABLE_PROJECTS ${DEFAULT_PROJECTS} CACHE STRING "") + +# This option enables linking stage2 clang statically with the runtimes +# (libc++ and compiler-rt) from stage1. In theory this will give the +# binaries better performance and make them more portable. However, +# this configuration is not well tested and causes build failures with +# the flang-rt tests cases, since the -stclib=libc++ flag does not +# get propagated to the runtimes build. There is also a separate +# issue on Darwin where clang will use the local libc++ headers, but +# link with system libc++ which can cause some incompatibilities. +# See https://github.com/llvm/llvm-project/issues/77653 +# Because of these problems, this option will default to OFF. +set(LLVM_RELEASE_ENABLE_LINK_LOCAL_RUNTIMES OFF CACHE BOOL "") + # Note we don't need to add install here, since it is one of the pre-defined # steps. set(LLVM_RELEASE_FINAL_STAGE_TARGETS "clang;package;check-all;check-llvm;check-clang" CACHE STRING "") @@ -55,8 +68,12 @@ set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") set(STAGE1_PROJECTS "clang") +# Need to build compiler-rt in order to use PGO for later stages. +set(STAGE1_RUNTIMES "compiler-rt") # Build all runtimes so we can statically link them into the stage2 compiler. -set(STAGE1_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind") +if(LLVM_RELEASE_ENABLE_LINK_LOCAL_RUNTIMES) + list(APPEND STAGE1_RUNTIMES "libcxx;libcxxabi;libunwind") +endif() if (LLVM_RELEASE_ENABLE_PGO) list(APPEND STAGE1_PROJECTS "lld") @@ -118,11 +135,13 @@ set_instrument_and_final_stage_var(LLVM_ENABLE_LTO "${LLVM_RELEASE_ENABLE_LTO}" if (LLVM_RELEASE_ENABLE_LTO) set_instrument_and_final_stage_var(LLVM_ENABLE_LLD "ON" BOOL) endif() -set_instrument_and_final_stage_var(LLVM_ENABLE_LIBCXX "ON" BOOL) -set_instrument_and_final_stage_var(LLVM_STATIC_LINK_CXX_STDLIB "ON" BOOL) -set(RELEASE_LINKER_FLAGS "-rtlib=compiler-rt --unwindlib=libunwind") -if(NOT ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") - set(RELEASE_LINKER_FLAGS "${RELEASE_LINKER_FLAGS} -static-libgcc") +if(LLVM_RELEASE_ENABLE_LINK_LOCAL_RUNTIMES) + set_instrument_and_final_stage_var(LLVM_ENABLE_LIBCXX "ON" BOOL) + set_instrument_and_final_stage_var(LLVM_STATIC_LINK_CXX_STDLIB "ON" BOOL) + set(RELEASE_LINKER_FLAGS "-rtlib=compiler-rt --unwindlib=libunwind") + if(NOT ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") + set(RELEASE_LINKER_FLAGS "${RELEASE_LINKER_FLAGS} -static-libgcc") + endif() endif() # Set flags for bolt @@ -130,9 +149,11 @@ if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux") set(RELEASE_LINKER_FLAGS "${RELEASE_LINKER_FLAGS} -Wl,--emit-relocs,-znow") endif() -set_instrument_and_final_stage_var(CMAKE_EXE_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) -set_instrument_and_final_stage_var(CMAKE_SHARED_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) -set_instrument_and_final_stage_var(CMAKE_MODULE_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) +if (RELEASE_LINKER_FLAGS) + set_instrument_and_final_stage_var(CMAKE_EXE_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) + set_instrument_and_final_stage_var(CMAKE_SHARED_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) + set_instrument_and_final_stage_var(CMAKE_MODULE_LINKER_FLAGS ${RELEASE_LINKER_FLAGS} STRING) +endif() # Final Stage Config (stage2) set_final_stage_var(LLVM_ENABLE_RUNTIMES "${LLVM_RELEASE_ENABLE_RUNTIMES}" STRING) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0e21ef0244f78..cdeaf3b2509c1 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6390,6 +6390,14 @@ the configuration (without a prefix: ``Auto``). IF (...) vs. IF(...) + * ``bool AfterNot`` If ``true``, put a space between alternative operator ``not`` and the + opening parenthesis. + + .. code-block:: c++ + + true: false: + return not (a || b); vs. return not(a || b); + * ``bool AfterOverloadedOperator`` If ``true``, put a space between operator overloading and opening parentheses. diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst index 913291c954447..96eb498bc48b6 100644 --- a/clang/docs/PointerAuthentication.rst +++ b/clang/docs/PointerAuthentication.rst @@ -47,16 +47,16 @@ This document serves four purposes: - It documents several language extensions that are useful on targets using pointer authentication. -- It will eventually present a theory of operation for the security mitigation, - describing the basic requirements for correctness, various weaknesses in the - mechanism, and ways in which programmers can strengthen its protections - (including recommendations for language implementors). +- It presents a theory of operation for the security mitigation, describing the + basic requirements for correctness, various weaknesses in the mechanism, and + ways in which programmers can strengthen its protections (including + recommendations for language implementors). -- It will eventually document the language ABIs currently used for C, C++, - Objective-C, and Swift on arm64e, although these are not yet stable on any - target. +- It documents the stable ABI of the C, C++, and Objective-C languages on arm64e + platforms. -Basic Concepts + +Basic concepts -------------- The simple address of an object or function is a **raw pointer**. A raw @@ -125,7 +125,7 @@ independently for I and D keys.) interfaces or as primitives in a compiler IR because they expose raw pointers. Raw pointers require special attention in the language implementation to avoid the accidental creation of exploitable code - sequences. + sequences; see the section on `Attackable code sequences`_. The following details are all implementation-defined: @@ -167,10 +167,15 @@ a cryptographic signature, other implementations may be possible. See signing key, and stores it in the high bits as the signature. ``auth`` removes the signature, computes the same hash, and compares the result with the stored signature. ``strip`` removes the signature without - authenticating it. While ``aut*`` instructions do not themselves trap on - failure in Armv8.3 PAuth, they do with the later optional FPAC extension. - An implementation can also choose to emulate this trapping behavior by - emitting additional instructions around ``aut*``. + authenticating it. The ``aut`` instructions in the baseline Armv8.3 PAuth + feature do not guarantee to trap on authentication failure; instead, they + simply corrupt the pointer so that later uses will likely trap. Unless the + "later use" follows immediately and cannot be recovered from (e.g. with a + signal handler), this does not provide adequate protection against + `authentication oracles`_, so implementations must emit additional + instructions to force an immediate trap. This is unnecessary if the + processor provides the optional ``FPAC`` extension, which guarantees an + immediate trap. - ``sign_generic`` corresponds to the ``pacga`` instruction, which takes two 64-bit values and produces a 64-bit cryptographic hash. Implementations of @@ -234,7 +239,7 @@ implementation-defined. .. _Signing schemas: -Signing Schemas +Signing schemas ~~~~~~~~~~~~~~~ Correct use of pointer authentication requires the signing code and the @@ -255,33 +260,172 @@ signing schema breaks down even more simply: It is important that the signing schema be independently derived at all signing and authentication sites. Preferably, the schema should be hard-coded everywhere it is needed, but at the very least, it must not be derived by -inspecting information stored along with the pointer. +inspecting information stored along with the pointer. See the section on +`Attacks on pointer authentication`_ for more information. -Language Features ------------------ -There is currently one main pointer authentication language feature: +Language features +----------------- -- The language provides the ```` intrinsic interface for manually - signing and authenticating pointers in code. These can be used in +There are three levels of the pointer authentication language feature: + +- The language implementation automatically signs and authenticates function + pointers (and certain data pointers) across a variety of standard situations, + including return addresses, function pointers, and C++ virtual functions. The + intent is for all pointers to code in program memory to be signed in some way + and for all branches to code in program text to authenticate those + signatures. In addition to the code pointers themselves, we also use pointer + authentication to protect data values that directly or indirectly influence + control flow or program integrity, or can provide attackers with some other + powerful program compromise. + +- The language also provides extensions to override the default rules used by + the language implementation. For example, the ``__ptrauth`` type qualifier + can be used to change how pointers or pointer sized integers are signed when + they are stored in a particular variable or field; this provides much stronger + protection than is guaranteed by the default rules for C function and data + pointers. + +- Finally, the language provides the ```` intrinsic interface for + manually signing and authenticating pointers in code. These can be used in circumstances where very specific behavior is required. +Language implementation +~~~~~~~~~~~~~~~~~~~~~~~ + +For the most part, pointer authentication is an unobserved detail of the +implementation of the programming language. Any element of the language +implementation that would perform an indirect branch to a pointer is implicitly +altered so that the pointer is signed when first constructed and authenticated +when the branch is performed. This includes: + +- indirect-call features in the programming language, such as C function + pointers, C++ virtual functions, C++ member function pointers, the "blocks" + C extension, and so on; + +- returning from a function, no matter how it is called; and + +- indirect calls introduced by the implementation, such as branches through the + global offset table (GOT) used to implement direct calls to functions defined + outside of the current shared object. + +For more information about this, see the `Language ABI`_ section. + +However, some aspects of the implementation are observable by the programmer or +otherwise require special notice. + +C data pointers +^^^^^^^^^^^^^^^ + +The current implementation in Clang does not sign pointers to ordinary data by +default. For a partial explanation of the reasoning behind this, see the +`Theory of Operation`_ section. + +A specific data pointer which is more security-sensitive than most can be +signed using the `__ptrauth qualifier`_ or using the ```` +intrinsics. + +C function pointers +^^^^^^^^^^^^^^^^^^^ + +The C standard imposes restrictions on the representation and semantics of +function pointer types which make it difficult to achieve satisfactory +signature diversity in the default language rules. See `Attacks on pointer +authentication`_ for more information about signature diversity. Programmers +should strongly consider using the ``__ptrauth`` qualifier to improve the +protections for important function pointers, such as the components of of +a hand-rolled "v-table"; see the section on the `__ptrauth qualifier`_ for +details. + +The value of a pointer to a C function includes a signature, even when the +value is cast to a non-function-pointer type like ``void*`` or ``intptr_t``. On +implementations that use high bits to store the signature, this means that +relational comparisons and hashes will vary according to the exact signature +value, which is likely to change between executions of a program. In some +implementations, it may also vary based on the exact function pointer type. + +Null pointers +^^^^^^^^^^^^^ + +In principle, an implementation could derive the signed null pointer value +simply by applying the standard signing algorithm to the raw null pointer +value. However, for likely signing algorithms, this would mean that the signed +null pointer value would no longer be statically known, which would have many +negative consequences. For one, it would become substantially more expensive +to emit null pointer values or to perform null-pointer checks. For another, +the pervasive (even if technically unportable) assumption that null pointers +are bitwise zero would be invalidated, making it substantially more difficult +to adopt pointer authentication, as well as weakening common optimizations for +zero-initialized memory such as the use of ``.bzz`` sections. Therefore it is +beneficial to treat null pointers specially by giving them their usual +representation. On AArch64, this requires additional code when working with +possibly-null pointers, such as when copying a pointer field that has been +signed with address diversity. + +While this representation of nulls is the safest option for the general case, +there are some situations in which a null pointer may have important semantic +or security impact. For that purpose Clang has the concept of a pointer +authentication schema that signs and authenticates null values. + +Return addresses +^^^^^^^^^^^^^^^^ + +The current implementation in Clang implicitly signs the return addresses in +function calls. While the value of the return address is technically an +implementation detail of a function, there are some important libraries and +development tools which rely on manually walking the chain of stack frames. +These tools must be updated to correctly account for pointer authentication, +either by stripping signatures (if security is not important for the tool, e.g. +if it is capturing a stack trace during a crash) or properly authenticating +them. More information about how these values are signed is available in the +`Language ABI`_ section. + +C++ virtual functions +^^^^^^^^^^^^^^^^^^^^^ + +The current implementation in Clang signs virtual function pointers with +a discriminator derived from the full signature of the overridden method, +including the method name and parameter types. It is possible to write C++ +code that relies on v-table layout remaining constant despite changes to +a method signature; for example, a parameter might be a ``typedef`` that +resolves to a different type based on a build setting. Such code violates +C++'s One Definition Rule (ODR), but that violation is not normally detected; +however, pointer authentication will detect it. -Language Extensions +Language extensions ~~~~~~~~~~~~~~~~~~~ -Feature Testing +Feature testing ^^^^^^^^^^^^^^^ Whether the current target uses pointer authentication can be tested for with a number of different tests. -- ``__has_feature(ptrauth_intrinsics)`` is true if ```` provides its - normal interface. This may be true even on targets where pointer - authentication is not enabled by default. +- ``__PTRAUTH__`` macro is defined if ```` provides its normal + interface. This implies support for the pointer authentication intrinsics + and the ``__ptrauth`` qualifier. -__ptrauth Qualifier -^^^^^^^^^^^^^^^^^^^ +- ``__has_feature(ptrauth_returns)`` is true if the target uses pointer + authentication to protect return addresses. + +- ``__has_feature(ptrauth_calls)`` is true if the target uses pointer + authentication to protect indirect branches. On arm64e this implies + ``__has_feature(ptrauth_returns)``, ``__has_feature(ptrauth_intrinsics)``, + and the ``__PTRAUTH__`` macro. + +- For backwards compatibility purposes ``__has_feature(ptrauth_intrinsics)`` + and ``__has_feature(ptrauth_qualifier)`` are available on arm64e targets. + These features are synonymous with each other, and are equivalent to testing + for the ``__PTRAUTH__`` macro definition. Use of these features should be + restricted to cases where backwards compatibility is required, and should be + paired with ``defined(__PTRAUTH__)``. + + +Clang provides several other tests only for historical purposes; for current +purposes they are all equivalent to ``ptrauth_calls``. + +``__ptrauth`` qualifier +^^^^^^^^^^^^^^^^^^^^^^^ ``__ptrauth(key, address, discriminator)`` is an extended type qualifier which causes so-qualified objects to hold pointers or pointer sized @@ -293,6 +437,11 @@ type, either to a function or to an object, or a pointer sized integer. It currently cannot be an Objective-C pointer type, a C++ reference type, or a block pointer type; these restrictions may be lifted in the future. +The current implementation in Clang is known to not provide adequate safety +guarantees against the creation of `signing oracles`_ when assigning data +pointers to ``__ptrauth``-qualified gl-values. See the section on `safe +derivation`_ for more information. + The qualifier's operands are as follows: - ``key`` - an expression evaluating to a key value from ````; must @@ -327,6 +476,57 @@ a discriminator determined as follows: is ``ptrauth_blend_discriminator(&x, discriminator)``; see `ptrauth_blend_discriminator`_. +Non-triviality from address diversity ++++++++++++++++++++++++++++++++++++++ + +Address diversity must impose additional restrictions in order to allow the +implementation to correctly copy values. In C++, a type qualified with address +diversity is treated like a class type with non-trivial copy/move constructors +and assignment operators, with the usual effect on containing classes and +unions. C does not have a standard concept of non-triviality, and so we must +describe the basic rules here, with the intention of imitating the emergent +rules of C++: + +- A type may be **non-trivial to copy**. + +- A type may also be **illegal to copy**. Types that are illegal to copy are + always non-trivial to copy. + +- A type may also be **address-sensitive**. This includes types that use self + referencing pointers, data protected by address diversified pointer + authentication, or other similar concepts. + +- A type qualified with a ``ptrauth`` qualifier or implicit authentication + schema that requires address diversity is non-trivial to copy and + address-sensitive. + +- An array type is illegal to copy, non-trivial to copy, or address-sensitive + if its element type is illegal to copy, non-trivial to copy, or + address-sensitive, respectively. + +- A struct type is illegal to copy, non-trivial to copy, or address-sensitive + if it has a field whose type is illegal to copy, non-trivial to copy, or + address-sensitive, respectively. + +- A union type is both illegal and non-trivial to copy if it has a field whose + type is non-trivial or illegal to copy. + +- A union type is address-sensitive if it has a field whose type is + address-sensitive. + +- A program is ill-formed if it uses a type that is illegal to copy as + a function parameter, argument, or return type. + +- A program is ill-formed if an expression requires a type to be copied that is + illegal to copy. + +- Otherwise, copying a type that is non-trivial to copy correctly copies its + subobjects. + +- Types that are address-sensitive must always be passed and returned + indirectly. Thus, changing the address-sensitivity of a type may be + ABI-breaking even if its size and alignment do not change. + ```` ~~~~~~~~~~~~~~~ @@ -433,7 +633,7 @@ Produce a signed pointer for the given raw pointer without applying any authentication or extra treatment. This operation is not required to have the same behavior on a null pointer that the language implementation would. -This is a treacherous operation that can easily result in signing oracles. +This is a treacherous operation that can easily result in `signing oracles`_. Programs should use it seldom and carefully. ``ptrauth_auth_and_resign`` @@ -454,7 +654,29 @@ a null pointer that the language implementation would. The code sequence produced for this operation must not be directly attackable. However, if the discriminator values are not constant integers, their computations may still be attackable. In the future, Clang should be enhanced -to guaranteed non-attackability if these expressions are safely-derived. +to guaranteed non-attackability if these expressions are +:ref:`safely-derived`. + +``ptrauth_auth_function`` +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_auth_function(pointer, key, discriminator) + +Authenticate that ``pointer`` is signed with ``key`` and ``discriminator`` and +re-sign it to the standard schema for a function pointer of its type. + +``pointer`` must have function pointer type. The result will have the same +type as ``pointer``. This operation is not required to have the same behavior +on a null pointer that the language implementation would. + +This operation makes the same attackability guarantees as +``ptrauth_auth_and_resign``. + +If this operation appears syntactically as the function operand of a call, +Clang guarantees that the call will directly authenticate the function value +using the given schema rather than re-signing to the standard schema. ``ptrauth_auth_data`` ^^^^^^^^^^^^^^^^^^^^^ @@ -500,12 +722,921 @@ type. Implementations are not required to make all bits of the result equally significant; in particular, some implementations are known to not leave meaningful data in the low bits. +Standard ``__ptrauth`` qualifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +```` additionally provides several macros which expand to +``__ptrauth`` qualifiers for common ABI situations. + +For convenience, these macros expand to nothing when pointer authentication is +disabled. + +These macros can be found in the header; some details of these macros may be +unstable or implementation-specific. + + +Theory of operation +------------------- + +The threat model of pointer authentication is as follows: + +- The attacker has the ability to read and write to a certain range of + addresses, possibly the entire address space. However, they are constrained + by the normal rules of the process: for example, they cannot write to memory + that is mapped read-only, and if they access unmapped memory it will trigger + a trap. + +- The attacker has no ability to add arbitrary executable code to the program. + For example, the program does not include malicious code to begin with, and + the attacker cannot alter existing instructions, load a malicious shared + library, or remap writable pages as executable. If the attacker wants to get + the process to perform a specific sequence of actions, they must somehow + subvert the normal control flow of the process. + +In both of the above paragraphs, it is merely assumed that the attacker's +*current* capabilities are restricted; that is, their current exploit does not +directly give them the power to do these things. The attacker's immediate goal +may well be to leverage their exploit to gain these capabilities, e.g. to load +a malicious dynamic library into the process, even though the process does not +directly contain code to do so. + +Note that any bug that fits the above threat model can be immediately exploited +as a denial-of-service attack by simply performing an illegal access and +crashing the program. Pointer authentication cannot protect against this. +While denial-of-service attacks are unfortunate, they are also unquestionably +the best possible result of a bug this severe. Therefore, pointer authentication +enthusiastically embraces the idea of halting the program on a pointer +authentication failure rather than continuing in a possibly-compromised state. + +Pointer authentication is a form of control-flow integrity (CFI) enforcement. +The basic security hypothesis behind CFI enforcement is that many bugs can only +be usefully exploited (other than as a denial-of-service) by leveraging them to +subvert the control flow of the program. If this is true, then by inhibiting or +limiting that subversion, it may be possible to largely mitigate the security +consequences of those bugs by rendering them impractical (or, ideally, +impossible) to exploit. + +Every indirect branch in a program has a purpose. Using human intelligence, a +programmer can describe where a particular branch *should* go according to this +purpose: a ``return`` in ``printf`` should return to the call site, a particular +call in ``qsort`` should call the comparator that was passed in as an argument, +and so on. But for CFI to enforce that every branch in a program goes where it +*should* in this sense would require CFI to perfectly enforce every semantic +rule of the program's abstract machine; that is, it would require making the +programming environment perfectly sound. That is out of scope. Instead, the +goal of CFI is merely to catch attempts to make a branch go somewhere that its +obviously *shouldn't* for its purpose: for example, to stop a call from +branching into the middle of a function rather than its beginning. As the +information available to CFI gets better about the purpose of the branch, CFI +can enforce tighter and tighter restrictions on where the branch is permitted to +go. Still, ultimately CFI cannot make the program sound. This may help explain +why pointer authentication makes some of the choices it does: for example, to +sign and authenticate mostly code pointers rather than every pointer in the +program. Preventing attackers from redirecting branches is both particularly +important and particularly approachable as a goal. Detecting corruption more +broadly is infeasible with these techniques, and the attempt would have far +higher cost. + +Attacks on pointer authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pointer authentication works as follows. Every indirect branch in a program has +a purpose. For every purpose, the implementation chooses a +:ref:`signing schema`. At some place where a pointer is known +to be correct for its purpose, it is signed according to the purpose's schema. +At every place where the pointer is needed for its purpose, it is authenticated +according to the purpose's schema. If that authentication fails, the program is +halted. + +There are a variety of ways to attack this. + +Attacks of interest to programmers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These attacks arise from weaknesses in the default protections offered by +pointer authentication. They can be addressed by using attributes or intrinsics +to opt in to stronger protection. + +Substitution attacks +++++++++++++++++++++ + +An attacker can simply overwrite a pointer intended for one purpose with a +pointer intended for another purpose if both purposes use the same signing +schema and that schema does not use address diversity. + +The most common source of this weakness is when code relies on using the default +language rules for C function pointers. The current implementation uses the +exact same signing schema for all C function pointers, even for functions of +substantially different type. While efforts are ongoing to improve constant +diversity for C function pointers of different type, there are necessary limits +to this. The C standard requires function pointers to be copyable with +``memcpy``, which means that function pointers can never use address diversity. +Furthermore, even if a function pointer can only be replaced with another +function of the exact same type, that can still be useful to an attacker, as in +the following example of a hand-rolled "v-table": + +.. code-block:: c + + struct ObjectOperations { + void (*retain)(Object *); + void (*release)(Object *); + void (*deallocate)(Object *); + void (*logStatus)(Object *); + }; + +The weakness in this design is that by lacking any context specific +discriminator, this means an attacker can substitute any of these fields with +any other function pointer signed with the default schema. Similarly the lack of +address diversity allows an attacker to replace the functions in one type's +"v-table" with those of another. This can be mitigated by overriding the default +authentication schema with a more specific signing schema for each purpose. For +instance, in this example, the ``__ptrauth`` qualifier can be used with a +different constant discriminator for each field. Since there's no particular +reason it's important for this v-table to be copyable with ``memcpy``, the +functions can also be signed with address diversity: + +.. code-block:: c + + #if defined(__PTRAUTH__) + #define objectOperation(discriminator) \ + __ptrauth(ptrauth_key_function_pointer, 1, discriminator) + #else + #define objectOperation(discriminator) + #endif + + struct ObjectOperations { + void (*objectOperation(0xf017) retain)(Object *); + void (*objectOperation(0x2639) release)(Object *); + void (*objectOperation(0x8bb0) deallocate)(Object *); + void (*objectOperation(0xc5d4) logStatus)(Object *); + }; + +This weakness can also sometimes be mitigated by simply keeping the signed +pointer in constant memory, but this is less effective than using better signing +diversity. + +.. _Access path attacks: + +Access path attacks ++++++++++++++++++++ + +If a signed pointer is often accessed indirectly (that is, by first loading the +address of the object where the signed pointer is stored), an attacker can +affect uses of it by overwriting the intermediate pointer in the access path. + +The most common scenario exhibiting this weakness is an object with a pointer to +a "v-table" (a structure holding many function pointers). An attacker does not +need to replace a signed function pointer in the v-table if they can instead +simply replace the v-table pointer in the object with their own pointer --- +perhaps to memory where they've constructed their own v-table, or to existing +memory that coincidentally happens to contain a signed pointer at the right +offset that's been signed with the right signing schema. + +This attack arises because data pointers are not signed by default. It works +even if the signed pointer uses address diversity: address diversity merely +means that each pointer is signed with its own storage address, +which (by design) is invariant to changes in the accessing pointer. + +Using sufficiently diverse signing schemas within the v-table can provide +reasonably strong mitigation against this weakness. Always use address and type +diversity in v-tables to prevent attackers from assembling their own v-table. +Avoid re-using constant discriminators to prevent attackers from replacing a +v-table pointer with a pointer to totally unrelated memory that just happens to +contain an similarly-signed pointer, or reused memory containing a different +type. + +Further mitigation can be attained by signing pointers to v-tables. Any +signature at all should prevent attackers from forging v-table pointers; they +will need to somehow harvest an existing signed pointer from elsewhere in +memory. Using a meaningful constant discriminator will force this to be +harvested from an object with similar structure (e.g. a different implementation +of the same interface). Using address diversity will prevent such harvesting +entirely. However, care must be taken when sourcing the v-table pointer +originally; do not blindly sign a pointer that is not +:ref:`safely derived`. + +.. _Signing oracles: + +Signing oracles ++++++++++++++++ + +A signing oracle is a bit of code which can be exploited by an attacker to sign +an arbitrary pointer in a way that can later be recovered. Such oracles can be +used by attackers to forge signatures matching the oracle's signing schema, +which is likely to cause a total compromise of pointer authentication's +effectiveness. + +This attack only affects ordinary programmers if they are using certain +treacherous patterns of code. Currently this includes: + +- all uses of the ``__ptrauth_sign_unauthenticated`` intrinsic and +- assigning values to ``__ptrauth``-qualified l-values. + +Care must be taken in these situations to ensure that the pointer being signed +has been :ref:`safely derived` or is otherwise not possible to +attack. (In some cases, this may be challenging without compiler support.) + +A diagnostic will be added in the future for implicitly dangerous patterns of +code, such as assigning a non-safely-derived values to a +``__ptrauth``-qualified l-value. + +.. _Authentication oracles: + +Authentication oracles +++++++++++++++++++++++ + +An authentication oracle is a bit of code which can be exploited by an attacker +to leak whether a signed pointer is validly signed without halting the program +if it isn't. Such oracles can be used to forge signatures matching the oracle's +signing schema if the attacker can repeatedly invoke the oracle for different +candidate signed pointers. This is likely to cause a total compromise of pointer +authentication's effectiveness. + +There should be no way for an ordinary programmer to create an authentication +oracle using the current set of operations. However, implementation flaws in the +past have occasionally given rise to authentication oracles due to a failure to +immediately trap on authentication failure. + +The likelihood of creating an authentication oracle is why there is currently no +intrinsic which queries whether a signed pointer is validly signed. + + +Attacks of interest to implementors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These attacks are not inherent to the model; they arise from mistakes in either +implementing or using the `sign` and `auth` operations. Avoiding these mistakes +requires careful work throughout the system. + +Failure to trap on authentication failure ++++++++++++++++++++++++++++++++++++++++++ + +Any failure to halt the program on an authentication failure is likely to be +exploitable by attackers to create an +:ref:`authentication oracle`. + +There are several different ways to introduce this problem: + +- The implementation might try to halt the program in some way that can be + intercepted. + + For example, the Armv8.3 ``aut`` instructions do not directly trap on + authentication failure on processors that lack the ``FPAC`` extension. + Instead, they corrupt their results to be invalid pointers, with the idea that + subsequent uses of those pointers will trigger traps as bad memory accesses. + However, most kernels do not immediately halt programs that trap due to bad + memory accesses; instead, they notify the process to give it an opportunity to + recover. If this happens with an ``auth`` failure, the attacker may be able to + exploit the recovery path in a way that creates an oracle. Kernels must + provide a way for a process to trap unrecoverably, and this should cover all + ``FPAC`` traps. Compilers must ensure that ``auth`` failures trigger an + unrecoverable trap, ideally by taking advantage of ``FPAC``, but if necessary + by emitting extra instructions. + +- A compiler might use an intermediate representation (IR) for ``sign`` and + ``auth`` operations that cannot make adequate correctness guarantees. + + For example, suppose that an IR uses ARMv8.3-like semantics for ``auth``: the + operation merely corrupts its result on failure instead of promising to trap. + A frontend might emit patterns of IR that always follow an ``auth`` with a + memory access, thinking that this ensures correctness. But if the IR can be + transformed to insert code between the ``auth`` and the access, or if the + ``auth`` can be speculated, then this potentially creates an oracle. It is + better for ``auth`` to semantically guarantee to trap, potentially requiring + an explicit check in the generated code. An ARMv8.3-like target can avoid this + explicit check in the common case by recognizing the pattern of an ``auth`` + followed immediately by an access. + +Attackable code sequences ++++++++++++++++++++++++++ + +If code that is part of a pointer authentication operation is interleaved with +code that may itself be vulnerable to attacks, an attacker may be able to use +this to create a :ref:`signing` or +:ref:`authentication` oracle. + +For example, suppose that the compiler is generating a call to a function and +passing two arguments: a signed constant pointer and a value derived from a +call. In ARMv8.3, this code might look like so: + +.. code-block:: asm + + adr x19, _callback. ; compute &_callback + paciza x19 ; sign it with a constant discriminator of 0 + blr _argGenerator ; call _argGenerator() (returns in x0) + mov x1, x0 ; move call result to second arg register + mov x0, x19 ; move signed &_callback to first arg register + blr _function ; call _function + +This code is correct, as would be a sequencing that does *both* the ``adr`` and +the ``paciza`` after the call to ``_argGenerator``. But a sequence that +computes the address of ``_callback`` but leaves it as a raw pointer in a +register during the call to ``_argGenerator`` would be vulnerable: + +.. code-block:: asm + + adr x19, _callback. ; compute &_callback + blr _argGenerator ; call _argGenerator() (returns in x0) + mov x1, x0 ; move call result to second arg register + paciza x19 ; sign &_callback + mov x0, x19 ; move signed &_callback to first arg register + blr _function ; call _function + +If ``_argGenerator`` spills ``x19`` (a callee-save register), and if the +attacker can perform a write during this call, then the attacker can overwrite +the spill slot with an arbitrary pointer that will eventually be unconditionally +signed after the function returns. This would be a signing oracle. + +The implementation can avoid this by obeying two basic rules: + +- The compiler's intermediate representations (IR) should not provide operations + that expose intermediate raw pointers. This may require providing extra + operations that perform useful combinations of operations. + + For example, there should be an "atomic" auth-and-resign operation that should + be used instead of emitting an ``auth`` operation whose result is fed into a + ``sign``. + + Similarly, if a pointer should be authenticated as part of doing a memory + access or a call, then the access or call should be decorated with enough + information to perform the authentication; there should not be a separate + ``auth`` whose result is used as the pointer operand for the access or call. + (In LLVM IR, we do this for calls, but not yet for loads or stores.) + + "Operations" includes things like materializing a signed value to a known + function or global variable. The compiler must be able to recognize and emit + this as a unified operation, rather than potentially splitting it up as in + the example above. + +- The compiler backend should not be too aggressive about scheduling + instructions that are part of a pointer authentication operation. This may + require custom code-generation of these operations in some cases. + +Register clobbering ++++++++++++++++++++ + +As a refinement of the section on `Attackable code sequences`_, if the attacker +has the ability to modify arbitrary *register* state at arbitrary points in the +program, then special care must be taken. + +For example, ARMv8.3 might materialize a signed function pointer like so: + +.. code-block:: asm + + adr x0, _callback. ; compute &_callback + paciza x0 ; sign it with a constant discriminator of 0 + +If an attacker has the ability to overwrite ``x0`` between these two +instructions, this code sequence is vulnerable to becoming a signing oracle. + +For the most part, this sort of attack is not possible: it is a basic element of +the design of modern computation that register state is private and inviolable. +However, in systems that support asynchronous interrupts, this property requires +the cooperation of the interrupt-handling code. If that code saves register +state to memory, and that memory can be overwritten by an attacker, then +essentially the attack can overwrite arbitrary register state at an arbitrary +point. This could be a concern if the threat model includes attacks on the +kernel or if the program uses user-space preemptive multitasking. + +(Readers might object that an attacker cannot rely on asynchronous interrupts +triggering at an exact instruction boundary. In fact, researchers have had some +success in doing exactly that. Even ignoring that, though, we should aim to +protect against lucky attackers just as much as good ones.) + +To protect against this, saved register state must be at least partially signed +(using something like `ptrauth_sign_generic_data`_). This is required for +correctness anyway because saved thread states include security-critical +registers such as SP, FP, PC, and LR (where applicable). Ideally, this +signature would cover all the registers, but since saving and restoring +registers can be very performance-sensitive, that may not be acceptable. It is +sufficient to set aside a small number of scratch registers that will be +guaranteed to be preserved correctly; the compiler can then be careful to only +store critical values like intermediate raw pointers in those registers. + +``setjmp`` and ``longjmp`` should sign and authenticate the core registers (SP, +FP, PC, and LR), but they do not need to worry about intermediate values because +``setjmp`` can only be called synchronously, and the compiler should never +schedule pointer-authentication operations interleaved with arbitrary calls. + +.. _Relative addresses: + +Attacks on relative addressing +++++++++++++++++++++++++++++++ + +Relative addressing is a technique used to compress and reduce the load-time +cost of infrequently-used global data. The pointer authentication system is +unlikely to support signing or authenticating a relative address, and in most +cases it would defeat the point to do so: it would take additional storage +space, and applying the signature would take extra work at load time. + +Relative addressing is not precluded by the use of pointer authentication, but +it does take extra considerations to make it secure: + +- Relative addresses must only be stored in read-only memory. A writable + relative address can be overwritten to point nearly anywhere, making it + inherently insecure; this danger can only be compensated for with techniques + for protecting arbitrary data like `ptrauth_sign_generic_data`_. + +- Relative addresses must only be accessed through signed pointers with adequate + diversity. If an attacker can perform an `access path attack` to replace the + pointer through which the relative address is accessed, they can easily cause + the relative address to point wherever they want. + +Signature forging ++++++++++++++++++ + +If an attacker can exactly reproduce the behavior of the signing algorithm, and +they know all the correct inputs to it, then they can perfectly forge a +signature on an arbitrary pointer. + +There are three components to avoiding this mistake: + +- The abstract signing algorithm should be good: it should not have glaring + flaws which would allow attackers to predict its result with better than + random accuracy without knowing all the inputs (like the key values). + +- The key values should be kept secret. If at all possible, they should never + be stored in accessible memory, or perhaps only stored encrypted. + +- Contexts that are meant to be independently protected should use different + key values. For example, the kernel should not use the same keys as user + processes. Different user processes should also use different keys from each + other as much as possible, although this may pose its own technical + challenges. + +Remapping ++++++++++ + +If an attacker can change the memory protections on certain pages of the +program's memory, that can substantially weaken the protections afforded by +pointer authentication. + +- If an attacker can inject their own executable code, they can also certainly + inject code that can be used as a :ref:`signing oracle`. + The same is true if they can write to the instruction stream. + +- If an attacker can remap read-only program data sections to be writable, then + any use of :ref:`relative addresses` in global data becomes insecure. + +- On platforms that use them, if an attacker can remap the memory containing + the `global offset tables`_ as writable, then any unsigned pointers in those + tables are insecure. + +Remapping memory in this way often requires the attacker to have already +substantively subverted the control flow of the process. Nonetheless, if the +operating system has a mechanism for mapping pages in a way that cannot be +remapped, this should be used wherever possible. + +.. _Safe Derivation: + +Safe derivation +~~~~~~~~~~~~~~~ + +Whether a data pointer is stored, even briefly, as a raw pointer can affect the +security-correctness of a program. (Function pointers are never implicitly +stored as raw pointers; raw pointers to functions can only be produced with the +```` intrinsics.) Repeated re-signing can also impact performance. +Clang makes a modest set of guarantees in this area: + +- An expression of pointer type is said to be **safely derived** if: + + - it takes the address of a global variable or function, or + + - it is a load from a gl-value of ``__ptrauth``-qualified type, or + + - it is a load from read-only memory that has been initialized from a safely + derived source, such as the `data const` section of a binary or library. + +- If a value that is safely derived is assigned to a ``__ptrauth``-qualified + object, including by initialization, then the value will be directly signed as + appropriate for the target qualifier and will not be stored as a raw pointer. + +- If the function expression of a call is a gl-value of ``__ptrauth``-qualified + type, then the call will be authenticated directly according to the source + qualifier and will not be resigned to the default rule for a function pointer + of its type. + +These guarantees are known to be inadequate for data pointer security. In +particular, Clang should be enhanced to make the following guarantees: + +- A pointer should additionally be considered safely derived if it is: + + - the address of a gl-value that is safely derived, + + - the result of pointer arithmetic on a pointer that is safely derived (with + some restrictions on the integer operand), + + - the result of a comma operator where the second operand is safely derived, + + - the result of a conditional operator where the selected operand is safely + derived, or + + - the result of loading from a safely derived gl-value. + +- A gl-value should be considered safely derived if it is: + + - a dereference of a safely derived pointer, + + - a member access into a safely derived gl-value, or + + - a reference to a variable. + +- An access to a safely derived gl-value should be guaranteed to not allow + replacement of any of the safely-derived component values at any point in the + access. "Access" should include loading a function pointer. + +- Assignments should include pointer-arithmetic operators like ``+=``. + +Making these guarantees will require further work, including significant new +support in LLVM IR. + +Furthermore, Clang should implement a warning when assigning a data pointer that +is not safely derived to a ``__ptrauth``-qualified gl-value. + + +Language ABI +------------ + +This section describes the pointer-authentication ABI currently implemented in +Clang for the Apple arm64e target. As other targets adopt pointer +authentication, this section should be generalized to express their ABIs as +well. + +Key assignments +~~~~~~~~~~~~~~~ + +ARMv8.3 provides four abstract signing keys: ``IA``, ``IB``, ``DA``, and ``DB``. +The architecture designates ``IA`` and ``IB`` for signing code pointers and +``DA`` and ``DB`` for signing data pointers; this is reinforced by two +properties: + +- The ISA provides instructions that perform combined auth+call and auth+load + operations; these instructions can only use the ``I`` keys and ``D`` keys, + respectively. + +- AArch64's TBI feature can be separately enabled for code pointers (controlling + whether indirect-branch instructions ignore those bits) and data pointers + (controlling whether memory-access instructions) ignore those bits. If TBI is + enabled for a kind of pointer, the sign and auth operations preserve the TBI + bits when signing with an associated keys (at the cost of shrinking the number + of available signing bits by 8). + +arm64e then further subdivides the keys as follows: + +- The ``A`` keys are used for primarily "global" purposes like signing v-tables + and function pointers. These keys are sometimes called *process-independent* + or *cross-process* because on existing OSes they are not changed when changing + processes, although this is not a platform guarantee. + +- The ``B`` keys are used for primarily "local" purposes like signing return + addresses. These keys are sometimes called *process-specific* because they + are typically different between processes. However, they are in fact shared + across processes in one situation: systems which provide ``fork`` cannot + change these keys in the child process; they can only be changed during + ``exec``. + +Implementation-defined algorithms and quantities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The cryptographic hash algorithm used to compute signatures in ARMv8.3 is a +private detail of the hardware implementation. + +arm64e restricts constant discriminators (used in ``__ptrauth`` and +``ptrauth_blend_discriminator``) to the range from 0 to 65535, inclusive. A 0 +discriminator generally signifies that no blending is required; see the +documentation for ``ptrauth_blend_discriminator``. This range is somewhat +narrow but has two advantages: + +- The AArch64 ISA allows an arbitrary 16-bit immediate to be written over the + top 16 bits of a register in a single instruction: + + .. code-block:: asm + + movk xN, #0x4849, LSL 48 + + This is ideal for the discriminator blending operation because it adds minimal + code-size overhead and avoids overwriting any interesting bits from the + pointer. Blending in a wider constant discriminator would either clobber + interesting bits (e.g. if it was loaded with ``movk xN, #0x4c4f, LSL 32``) or + require significantly more code (e.g. if the discriminator was loaded with a + ``mov+bfi`` sequence). + +- It is possible to pack a 16-bit discriminator into loader metadata with + minimal compromises, whereas a wider discriminator would require extra + metadata storage and therefore significantly impact load times. + +The string hash used by ``ptrauth_string_discriminator`` is a 64-bit SipHash-2-4 +using the constant seed ``b5d4c9eb79104a796fec8b1b428781d4`` (big-endian), with +the result reduced by modulo to the range of non-zero discriminators (i.e. +``(rawHash % 65535) + 1``). + +Return addresses +~~~~~~~~~~~~~~~~ + +The kernel must ensure that attackers cannot replace LR due to an asynchronous +exception; see `Register clobbering`_. If this is done by generally protecting +LR, then functions which don't spill LR to the stack can avoid signing it +entirely. Otherwise, the return address must be signed; on arm64e it is signed +with the ``IB`` key using the stack pointer on entry as the discriminator. + +Protecting return addresses is of such particular importance that the ``IB`` key +is almost entirely reserved for this purpose. + +Global offset tables +~~~~~~~~~~~~~~~~~~~~ + +The global offset table (GOT) is not part of the language ABI, but it is a +common implementation technique for dynamic linking which deserves special +discussion here. + +Whenever possible, signed pointers should be materialized directly in code +rather than via the GOT, e.g. using an ``adrp+add+pac`` sequence on ARMv8.3. +This decreases the amount of work necessary at load time to initialize the GOT, +but more importantly, it defines away the potential for several attacks: + +- Attackers cannot change instructions, so there is no way to cause this code + sequence to materialize a different pointer, whereas an access via the GOT + always has *at minimum* a probabilistic chance to be the target of successful + `substitution attacks`_. + +- The GOT is a dense pool of fixed pointers at a fixed offset relative to code; + attackers can search this pool for useful pointers that can be used in + `substitution attacks`_, whereas pointers that are only materialized directly + are not so easily available. + +- Similarly, attackers can use `access path attacks`_ to replace a pointer to a + signed pointer with a pointer to the GOT if the signing schema used within the + GOT happens to be the same as the original pointer. This kind of collision + becomes much less likely to be useful the fewer pointers are in the GOT in the + first place. + +If this can be done for a symbol, then the compiler need only ensure that it +materializes the signed pointer using registers that are safe against +`register clobbering`_. + +However, many symbols can only be accessed via the GOT, e.g. because they +resolve to definitions outside of the current image. In this case, care must +be taken to ensure that using the GOT does not introduce weaknesses. + +- If the entire GOT can be mapped read-only after loading, then no signing is + required within the GOT. In fact, not signing pointers in the GOT is + preferable in this case because it makes the GOT useless for the harvesting + and access-path attacks above. Storing raw pointers in this way is usually + extremely unsafe, but for the special case of an immutable GOT entry it's fine + because the GOT is always accessed via an address that is directly + materialized in code and thus provably unattackable. (But see `Remapping`_.) + +- Otherwise, GOT entries which are used for producing a signed pointer constant + must be signed. The signing schema used in the GOT need not match the target + signing schema for the signed constant. To counteract the threats of + substitution attacks, it's best if GOT entries can be signed with address + diversity. Using a good constant discriminator as well (perhaps derived from + the symbol name) can make it less useful to use a pointer to the GOT as the + replacement in an :ref:`access path attack`. + +In either case, the compiler must ensure that materializing the address of a GOT +entry as part of producing a signed pointer constant is not vulnerable to +`register clobbering`_. If the linker also generates code for this, e.g. for +call stubs, this generated code must take the same precautions. + +Dynamic symbol lookup +~~~~~~~~~~~~~~~~~~~~~ + +On platforms that support dynamically loading or resolving symbols it is +necessary for them to define the pointer authentication semantics of the APIs +provided to perform such lookups. While the platform may choose to reply +unsigned pointers from such function and rely on the caller performing the +initial signing, doing so creates the opportunity for caller side errors that +create :ref:`signing oracles`. + +On arm64e the `dlsym` function is used to resolve a symbol at runtime. If the +resolved symbol is a function or other code pointer the returned pointer is +signed using the default function signing schema described in +:ref:`C function pointers`. If the resolved symbol is not a code pointer it is +returned as an unsigned pointer. + +.. _C function abi: + +C function pointers +~~~~~~~~~~~~~~~~~~~ + +On arm64e, C function pointers are currently signed with the ``IA`` key without +address diversity and with a constant discriminator of 0. + +The C and C++ standards do not permit C function pointers to be signed with +address diversity by default: in C++ terms, function pointer types are required +to be trivially copyable, which means they must be copyable with ``memcpy``. + +The use of a uniform constant discriminator greatly simplifies the adoption of +arm64e, but it is a significant weakness in the mitigation because it allows any +C function pointer to be replaced with another. Clang supports +`-fptrauth-function-pointer-type-discrimination`, which enables a variant ABI +that uses type discrimination for function pointers. When generating the type +based discriminator for a function type all primitive integer types are +considered equivalent due to the prevalence of mismatching integer parameter +types in real world code. Type discrimination of function pointers is +ABI-incompatible with the standard arm64e ABI, but it can be used in constrained +contexts such as embedded systems or in code that does not require function +pointer interoperation with the standard ABI (e.g. because it does not pass +function pointers back and forth, or only does so through +``__ptrauth``-qualified l-values). + +C++ virtual tables +~~~~~~~~~~~~~~~~~~ + +By default the pointer to a C++ virtual table is currently signed with the +``DA`` key, address diversity, and a constant discriminator equal to the string +hash (see `ptrauth_string_discriminator`_) of the mangled v-table identifier +of the primary base class for the v-table. To support existing code or ABI +constraints it is possible to use the `ptrauth_vtable_pointer` attribute to +override the schema used for the v-table pointer of the base type of +polymorphic class hierarchy. This attribute permits the configuration of the +key, address diversity mode, and any extra constant discriminator to be used. + +Virtual functions in a C++ virtual table are signed with the ``IA`` key, address +diversity, and a constant discriminator equal to the string hash (see +`ptrauth_string_discriminator`_) of the mangled name of the function which +originally gave rise to the v-table slot. + +C++ dynamic_cast +~~~~~~~~~~~~~~~~ + +C++'s ``dynamic_cast`` presents a difficulty relative to other polymorphic +languages that have a +`top type ` as the use of declaration +diversity for v-table pointers results in distinct signing schemas for each +isolated type hierarchy. As a result it is not possible for the Itanium ABI +defined ``__dynamic_cast`` entry point to directly authenticate the v-table +pointer of the provided object. + +The current implementation uses a forced authentication of the subject object's +v-table prior to invoking ``__dynamic_cast`` to partially verify that the +object's vtable is valid. The ``__dynamic_cast`` implementation currently relies +on this caller side check to limit the substitutability of the v-table pointer +with an incorrect or invalid v-table. The subsequent implementation of the +dynamic cast algorithm is built on pointer auth protected ``type_info`` objects. + +In future a richer solution may be developed to support vending the correct +authentication schema directly to the ``dynamic_cast`` implementation. + +C++ std::type_info v-table pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The v-table pointer of the ``std::type_info`` type is signed with the ``DA`` key +and no additional diversity. + +C++ member function pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A member function pointer is signed with the ``IA`` key, no address diversity, +and a constant discriminator equal to the string hash +(see `ptrauth_string_discriminator`_) of the member pointer type. Address +diversity is not permitted by C++ for member function pointers because they must +be trivially-copyable types. + +The Itanium C++ ABI specifies that member function pointers to virtual functions +simply store an offset to the correct v-table slot. This ABI cannot be used +securely with pointer authentication because there is no safe place to store the +constant discriminator for the target v-table slot: if it's stored with the +offset, an attacker can simply overwrite it with the right discriminator for the +offset. Even if the programmer never uses pointers to virtual functions, the +existence of this code path makes all member function pointer dereferences +insecure. + +arm64e changes this ABI so that virtual function pointers are stored using +dispatch thunks with vague linkage. Because arm64e supports interoperation with +``arm64`` code when pointer authentication is disabled, an arm64e member +function pointer dereference still recognizes the virtual-function +representation but uses an bogus discriminator on that path that should always +trap if pointer authentication is enabled dynamically. + +The use of dispatch thunks means that ``==`` on member function pointers is no +longer reliable for virtual functions, but this is acceptable because the +standard makes no guarantees about it in the first place. + +The use of dispatch thunks also is required to support declaration specific +authentication schemas for v-table pointers. + +C++ mangling +~~~~~~~~~~~~ + +When the ``__ptrauth`` qualifier appears in a C++ mangled name, +it is mangled as a vendor qualifier with the signature +``U9__ptrauthILjELbELjEE``. + +e.g. ``int * __ptrauth(1, 0, 1234)`` will be mangled as +``U9__ptrauthILj1ELb0ELj1234EE``. + +If the vtable pointer authentication scheme of a polymorphic class is overridden +we mangle the override information with the vendor qualifier +``__vtptrauth(int key, bool addressDiscriminated, unsigned extraDiscriminator)``, +where the extra discriminator is the explicit value the specified discrimination +mode evalutes to. + +Blocks +~~~~~~ + +Block pointers are data pointers which must interoperate with the ObjC `id` type +and therefore cannot be signed themselves. As blocks conform to the ObjC `id` +type, they contain an ``isa`` pointer signed as described +:ref:`below`. + +The invocation pointer in a block is signed with the ``IA`` key using address +diversity and a constant dicriminator of 0. Using a uniform discriminator is +seen as a weakness to be potentially improved, but this is tricky due to the +subtype polymorphism directly permitted for blocks. + +Block descriptors and ``__block`` variables can contain pointers to functions +that can be used to copy or destroy the object. These functions are signed with +the ``IA`` key, address diversity, and a constant discriminator of 0. The +structure of block descriptors is under consideration for improvement. + +Objective-C runtime +~~~~~~~~~~~~~~~~~~~ + +In addition to the compile time ABI design, the Objective-C runtime provides +additional protection to methods and other metadata that have been loaded into +the Objective-C method cache; this protection is private to the runtime. + +Objective-C methods +~~~~~~~~~~~~~~~~~~~ + +Objective-C method lists sign methods with the ``IA`` key using address +diversity and a constant discriminator of 0. Using a uniform constant +discriminator is believed to be acceptable because these tables are only +accessed internally to the Objective-C runtime. + +Objective-C class method list pointer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The method list pointer in Objective-C classes are signed with the ``DA`` key +using address diversity, and a constant discriminator of 0xC310. + +Objective-C class read-only data pointer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The read-only data pointer in Objective-C classes are signed with the ``DA`` key +using address diversity, and a constant discriminator of 0x61F8. + +.. _Objc isa and super: + +Objective-C ``isa`` and ``super`` pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An Objective-C object's ``isa`` and ``super`` pointers are both signed with +the ``DA`` key using address diversity and constant discriminators of 0x6AE1 +and 0x25DA respectively. + +Objective-C ``SEL`` pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, the type of an Objective-C instance variable of type ``SEL``, when +the qualifiers do not include an explicit ``__ptrauth`` qualifier, is adjusted +to be qualified with ``__ptrauth(ptrauth_key_asdb, 1, 0x57C2)``. + +This provides a measure of implicit at-rest protection to Objective-C classes +that store selectors, as in the common target-action design pattern. This +prevents attackers from overriding the selector to invoke an arbitrary different +method, which is a major attack vector in Objective-C. Since ``SEL`` values are +not normally passed around as signed pointers, there is a +:ref:`signing oracle` associated with the initialization of the +ivar, but the use of address and constant diversity limit the risks. + +The implicit qualifier means that the type of the ivar does not match its +declaration, which can cause type errors if the address of the ivar is taken: + +.. code-block:: ObjC + + @interface A : NSObject { + SEL _s; + } + @end + + void f(SEL *); + + @implementation A + -(void)g + { + f(&_s); + } + @end + +To fix such an mismatch the schema macro from ``: + +.. code-block:: ObjC + + #include + + void f(SEL __ptrauth_objc_sel*); +or less safely, and introducing the possibility of an +:ref:`signing or authentication oracle`, an unauthencaticated +temporary may be used as intermediate storage. -Alternative Implementations +Alternative implementations --------------------------- -Signature Storage +Signature storage ~~~~~~~~~~~~~~~~~ It is not critical for the security of pointer authentication that the @@ -536,7 +1667,7 @@ Storing the signature in the high bits, as Armv8.3 does, has several trade-offs: return signed pointers. This means that clients of these APIs will not require insecure code in order to correctly receive a function pointer. -Hashing vs. Encrypting Pointers +Hashing vs. encrypting pointers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Armv8.3 implements ``sign`` by computing a cryptographic hash and storing that diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bd7a4b20242fd..364ea632b40cb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -55,7 +55,7 @@ C/C++ Language Potentially Breaking Changes case for old-style offsetof idioms like ``((int)(&(((struct S *)0)->field)))``, to ensure they are not caught by these optimizations. It is also possible to use ``-fwrapv-pointer`` or ``-fno-delete-null-pointer-checks`` to make pointer arithmetic - on null pointers well-defined. (#GH130734, #GH130742, #GH130952) + on null pointers well-defined. (#GH130734, #GH130952) C++ Specific Potentially Breaking Changes ----------------------------------------- @@ -94,6 +94,7 @@ Clang Frontend Potentially Breaking Changes Clang Python Bindings Potentially Breaking Changes -------------------------------------------------- +- Return ``None`` instead of null cursors from ``Token.cursor`` - ``Cursor.from_location`` now returns ``None`` instead of a null cursor. This eliminates the last known source of null cursors. - Almost all ``Cursor`` methods now assert that they are called on non-null cursors. @@ -123,6 +124,8 @@ C++ Language Changes a perfect match (all conversion sequences are identity conversions) template candidates are not instantiated. Diagnostics that would have resulted from the instantiation of these template candidates are no longer produced. This aligns Clang closer to the behavior of GCC, and fixes (#GH62096), (#GH74581), and (#GH74581). +- Implemented `P2719R5 Type-aware allocation and deallocation functions `_ + as an extension in all C++ language modes. C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -359,6 +362,12 @@ Non-comprehensive list of changes in this release ARC-managed pointers and other pointer types. The prior behavior was overly strict and inconsistent with the ARC specification. +- Use of ``__has_feature`` to detect the ``ptrauth_qualifier`` and ``ptrauth_intrinsics`` + features has been deprecated, and is restricted to the arm64e target only. The + correct method to check for these features is to test for the ``__PTRAUTH__`` + macro. + + New Compiler Flags ------------------ @@ -376,6 +385,13 @@ New Compiler Flags - New options ``-g[no-]key-instructions`` added, disabled by default. Reduces jumpiness of debug stepping for optimized code in some debuggers (not LLDB at this time). Not recommended for use without optimizations. DWARF only. Note both the positive and negative flags imply ``-g``. +- New options ``-fthinlto-distributor=`` and ``-Xthinlto-distributor=`` added for Integrated Distributed ThinLTO (DTLTO). DTLTO enables the distribution of backend ThinLTO compilations via external distribution systems, such as Incredibuild, during the traditional link step. (#GH147265, `ThinLTODocs `_). + +- A new flag - `-static-libclosure` was introduced to support statically linking + the runtime for the Blocks extension on Windows. This flag currently only + changes the code generation, and even then, only on Windows. This does not + impact the linker behaviour like the other `-static-*` flags. + Deprecated Compiler Flags ------------------------- @@ -662,8 +678,8 @@ Improvements to Clang's diagnostics trigger a ``'Blue' is deprecated`` warning, which can be turned off with ``-Wno-deprecated-declarations-switch-case``. -- Split diagnosis of implicit integer comparison on negation to a new - diagnostic group ``-Wimplicit-int-comparison-on-negation``, grouped under +- Split diagnosis of implicit integer conversion on negation to a new + diagnostic group ``-Wimplicit-int-conversion-on-negation``, grouped under ``-Wimplicit-int-conversion``, so user can turn it off independently. - Improved the FixIts for unused lambda captures. @@ -674,7 +690,7 @@ Improvements to Clang's diagnostics #GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308, #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490, #GH36703, #GH32903, #GH23312, #GH69874. - + - Clang no longer emits a spurious -Wdangling-gsl warning in C++23 when iterating over an element of a temporary container in a range-based for loop.(#GH109793, #GH145164) @@ -800,6 +816,8 @@ Bug Fixes in This Version declaration statements. Clang now emits a warning for these patterns. (#GH141659) - Fixed false positives for redeclaration errors of using enum in nested scopes. (#GH147495) +- Fixed a crash in `clang-scan-deps` when a module with the same name is found + in different locations (#GH134404, #GH146976). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -949,7 +967,6 @@ Bug Fixes to C++ Support - Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608) - Fixed a pack substitution bug in deducing class template partial specializations. (#GH53609) - Fixed a crash when constant evaluating some explicit object member assignment operators. (#GH142835) -- Fixed an access checking bug when substituting into concepts (#GH115838) - Fix a bug where private access specifier of overloaded function not respected. (#GH107629) - Correctly handles calling an explicit object member function template overload set through its address (``(&Foo::bar)()``). @@ -967,6 +984,7 @@ Bug Fixes to C++ Support - Fix a crash with NTTP when instantiating local class. - Fixed a crash involving list-initialization of an empty class with a non-empty initializer list. (#GH147949) +- Fixed constant evaluation of equality comparisons of constexpr-unknown references. (#GH147663) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -993,6 +1011,19 @@ Miscellaneous Clang Crashes Fixed OpenACC Specific Changes ------------------------ +- OpenACC support, enabled via `-fopenacc` has reached a level of completeness + to finally be at least notionally usable. Currently, the OpenACC 3.4 + specification has been completely implemented for Sema and AST creation, so + nodes will show up in the AST after having been properly checked. Lowering is + currently a work in progress, with compute, loop, and combined constructs + partially implemented, plus a handful of data and executable constructs + implemented. Lowering will only work in Clang-IR mode (so only with a compiler + built with Clang-IR enabled, and with `-fclangir` used on the command line). + However, note that the Clang-IR implementation status is also quite partial, + so frequent 'not yet implemented' diagnostics should be expected. Also, the + ACC MLIR dialect does not currently implement any lowering to LLVM-IR, so no + code generation is possible for OpenACC. + Target Specific Changes ----------------------- @@ -1071,6 +1102,8 @@ Windows Support extensions are enabled. This allows for properly processing ``intsafe.h`` in the Windows SDK. +- Clang now supports `mipsel-windows-gnu` and `mipsel-windows-msvc` targets. + LoongArch Support ^^^^^^^^^^^^^^^^^ @@ -1119,9 +1152,19 @@ CUDA/HIP Language Changes CUDA Support ^^^^^^^^^^^^ +PowerPC Support +^^^^^^^^^^^^^^^ + +* Add `__dmr1024` type for Dense Math Facility. +* Add prototype for Dense Math Facility integer calculation builtins. + AIX Support ^^^^^^^^^^^ +* Fixed `-print-runtime-dir` to fallback to the target subdirectory (rather than OS subdirectory) if the runtime path is not found. +* Fixed `-print-runtime-dir` to find the correct runtime path if the triple has "unknown" as the environment component. +* Changed AIX targets to use the per-target runtime directories for compiler runtimes (i.e. `lib/clang/20/lib/aix` became `lib/clang/21/lib/powerpc-ibm-aix` and `clang/21/lib/powerpc64-ibm-aix`). + NetBSD Support ^^^^^^^^^^^^^^ @@ -1192,53 +1235,117 @@ Code Completion Static Analyzer --------------- -- Fixed a crash when C++20 parenthesized initializer lists are used. This issue - was causing a crash in clang-tidy. (#GH136041) New features ^^^^^^^^^^^^ -- A new flag - `-static-libclosure` was introduced to support statically linking - the runtime for the Blocks extension on Windows. This flag currently only - changes the code generation, and even then, only on Windows. This does not - impact the linker behaviour like the other `-static-*` flags. -- OpenACC support, enabled via `-fopenacc` has reached a level of completeness - to finally be at least notionally usable. Currently, the OpenACC 3.4 - specification has been completely implemented for Sema and AST creation, so - nodes will show up in the AST after having been properly checked. Lowering is - currently a work in progress, with compute, loop, and combined constructs - partially implemented, plus a handful of data and executable constructs - implemented. Lowering will only work in Clang-IR mode (so only with a compiler - built with Clang-IR enabled, and with `-fclangir` used on the command line). - However, note that the Clang-IR implementation status is also quite partial, - so frequent 'not yet implemented' diagnostics should be expected. Also, the - ACC MLIR dialect does not currently implement any lowering to LLVM-IR, so no - code generation is possible for OpenACC. -- Implemented `P2719R5 Type-aware allocation and deallocation functions `_ - as an extension in all C++ language modes. +- Added support for the ``[[clang::assume(cond)]]`` attribute, treating it as + ``__builtin_assume(cond)`` for better static analysis. (#GH129234) +- Introduced per-entry-point statistics to provide more detailed analysis metrics. + Documentation: :doc:`analyzer/developer-docs/Statistics` (#GH131175) + +- Added time-trace scopes for high-level analyzer steps to improve performance + debugging. Documentation: :doc:`analyzer/developer-docs/PerformanceInvestigation` + (#GH125508, #GH125884) + +- Enhanced the ``check::BlockEntrance`` checker callback to provide more granular + control over block-level analysis. + `Documentation (check::BlockEntrance) + `_ + (#GH140924) + +- Added a new checker ``core.FixedAddressDereference`` to detect dereferences + of fixed addresses, which can be useful for finding hard-coded memory + accesses. (#GH127191, #GH132404) Crash and bug fixes ^^^^^^^^^^^^^^^^^^^ -- Fixed a crash in ``UnixAPIMisuseChecker`` and ``MallocChecker`` when analyzing +- Fixed a regression introduced by clang-20 in #GH115918 that lead to false + positive reports when ``[[no_unique_address]]`` or empty base class + optimization techniques were used. Most notably, some ``std::unique_ptr`` + implementations. (#GH157467) + +- Fixed a crash when C++20 parenthesized initializer lists are used. + This affected a crash of the well-known lambda overloaded pattern. + (#GH136041, #GH135665) + +- Dropped an unjustified assertion, that was triggered in ``BugReporterVisitors.cpp`` + for variable initialization detection. (#GH125044) + +- Fixed a crash in ``unix.API`` and ``unix.Malloc`` when analyzing code with non-standard ``getline`` or ``getdelim`` function signatures. (#GH144884) +- Fixed crashes involving ``__builtin_bit_cast``. (#GH139188) + +- ``__datasizeof`` (C++) and ``_Countof`` (C) no longer cause a failed assertion + when given an operand of VLA type. (#GH151711) + +- Fixed a crash in ``alpha.core.CastSize``. (#GH134387) + +- Some ``cplusplus.PlacementNew`` false positives were fixed. (#GH150161) + Improvements ^^^^^^^^^^^^ +- Added option to assume at least one iteration in loops to reduce false positives. + (#GH125494) + - The checker option ``optin.cplusplus.VirtualCall:PureOnly`` was removed, - because it had been deprecated since 2019 and it is completely useless (it - was kept only for compatibility with pre-2019 versions, setting it to true is - equivalent to completely disabling the checker). + because it had been deprecated since 2019. (#GH131823) + +- Enhanced the ``core.StackAddressEscape`` to detect more cases of stack address + escapes, including return values for child stack frames. (#GH126620, #GH126986) + +- Improved the ``unix.BlockInCriticalSection`` to recognize ``O_NONBLOCK`` + streams and suppress reports in those cases. (#GH127049) + +- Better support for lambda-converted function pointers in analysis. (#GH144906) + +- Improved modeling of ``getcwd`` function in ``unix.StdCLibraryFunctions`` checker. + (#GH141076) + +- Enhanced the ``optin.core.EnumCastOutOfRange`` checker to ignore ``[[clang::flag_enum]]`` + enums. (#GH141232) + +- Improved handling of structured bindings captured by lambdas. (#GH132579, #GH91835) + +- Fixed unnamed bitfield handling in ``optin.cplusplus.UninitializedObject``. (#GH132427, #GH132001) + +- Enhanced iterator checker modeling for ``insert`` operations. (#GH132596) + +- Improved ``format`` attribute handling in ``optin.taint.GenericTaint``. (#GH132765) + +- Added support for ``consteval`` in ``ConditionBRVisitor::VisitTerminator``. + (#GH146859, #GH139130) + +- C standard streams are no longer invalidated by all C library function calls. + (#GH147766) + +- Enhanced store management with region-store-binding-limit to improve performance. + See `region-store-max-binding-fanout + `_ + config option. Overriding these options are discouraged, unless you know what you do. + (#GH127602) + +- Updated undefined assignment checker (``core.uninitialized.Assign``) diagnostics + to avoid using the term ``garbage``. (#GH126596) + +- Fixed false memory leak reports involving placement new. (#GH144341) + +- Avoided unnecessary super region invalidation in ``unix.cstring.*`` checkers. + (#GH146212, #GH143807) + +- Enhanced handling of tainted division-by-zero error paths in the + ``optin.taint.TaintedDiv`` checker. (#GH144491) Moved checkers ^^^^^^^^^^^^^^ -- After lots of improvements, the checker ``alpha.security.ArrayBoundV2`` is +- After lots of improvements, the checker ``alpha.security.ArrayBoundV2`` was renamed to ``security.ArrayBound``. As this checker is stable now, the old - checker ``alpha.security.ArrayBound`` (which was searching for the same kind - of bugs with an different, simpler and less accurate algorithm) is removed. + checker ``alpha.security.ArrayBound`` was removed. .. _release-notes-sanitizers: diff --git a/clang/docs/ThinLTO.rst b/clang/docs/ThinLTO.rst index c042547678919..8cb3e0b2b0d11 100644 --- a/clang/docs/ThinLTO.rst +++ b/clang/docs/ThinLTO.rst @@ -240,6 +240,53 @@ The ``BOOTSTRAP_LLVM_ENABLE_LTO=Thin`` will enable ThinLTO for stage 2 and stage 3 in case the compiler used for stage 1 does not support the ThinLTO option. +Integrated Distributed ThinLTO (DTLTO) +-------------------------------------- + +Integrated Distributed ThinLTO (DTLTO) enables the distribution of backend +ThinLTO compilations via external distribution systems, such as Incredibuild, +during the traditional link step. + +The implementation is documented here: https://llvm.org/docs/DTLTO.html. + +Command-Line Options +^^^^^^^^^^^^^^^^^^^^ + +DTLTO requires the LLD linker (``-fuse-ld=lld``). + +``-fthinlto-distributor=`` + - Specifies the ```` to the distributor process executable for DTLTO. + - If specified, ThinLTO backend compilations will be distributed by LLD. + +``-Xthinlto-distributor=`` + - Passes ```` to the distributor process (see ``-fthinlto-distributor=``). + - Can be specified multiple times to pass multiple options. + - Multiple options can also be specified by separating them with commas. + +If ``-fthinlto-distributor=`` is specified, Clang supplies the path to a +compiler to be executed remotely to perform the ThinLTO backend +compilations. Currently, this is Clang itself. + +Usage +^^^^^ + +Compilation is unchanged from ThinLTO. DTLTO options need to supplied for the link step: + +.. code-block:: console + + % clang -flto=thin -fthinlto-distributor=distribute.sh -Xthinlto-distributor=--verbose,--j10 -fuse-ld=lld file1.o file2.o + % clang -flto=thin -fthinlto-distributor=$(which python) -Xthinlto-distributor=distribute.py -fuse-ld=lld file1.o file2.o + +When using lld-link: + +.. code-block:: console + + % lld-link /out:a.exe file1.obj file2.obj /thinlto-distributor:distribute.exe /thinlto-remote-compiler:${LLVM}\bin\clang.exe /thinlto-distributor-arg:--verbose + +Note that currently, DTLTO is only supported in some LLD flavors. Support can +be added to other LLD flavours in the future. +See `DTLTO `_ for more information. + More Information ================ diff --git a/clang/docs/index.rst b/clang/docs/index.rst index 4871d05e932ae..f603ce34a0818 100644 --- a/clang/docs/index.rst +++ b/clang/docs/index.rst @@ -45,6 +45,7 @@ Using Clang as a Compiler BoundsSafetyImplPlans ControlFlowIntegrity LTOVisibility + PointerAuthentication SafeStack ShadowCallStack SourceBasedCodeCoverage diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index c35311c886413..b929585205aee 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -6953,6 +6953,21 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor); * @} */ +CINDEX_DEPRECATED +typedef void *CXRemapping; + +CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *); + +CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping +clang_getRemappingsFromFileList(const char **, unsigned); + +CINDEX_DEPRECATED CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping); + +CINDEX_DEPRECATED CINDEX_LINKAGE void +clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *); + +CINDEX_DEPRECATED CINDEX_LINKAGE void clang_remap_dispose(CXRemapping); + LLVM_CLANG_C_EXTERN_C_END #endif diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 9999a30c51ade..cb942ea865e2d 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -143,7 +143,7 @@ class APValue { AddrLabelDiff }; - class LValueBase { + class alignas(uint64_t) LValueBase { typedef llvm::PointerUnion PtrTy; diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8c27728c404dd..993eca8c47382 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -648,8 +648,7 @@ class ASTContext : public RefCountedBase { bool containsNonRelocatablePointerAuth(QualType T) { if (!isPointerAuthenticationAvailable()) return false; - return findPointerAuthContent(T) == - PointerAuthContent::AddressDiscriminatedData; + return findPointerAuthContent(T) != PointerAuthContent::None; } private: diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index fefdaba7f8bf5..76747d2b11811 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -9417,9 +9417,9 @@ def NonStringDocs : Documentation { let Category = DocCatDecl; let Content = [{ The ``nonstring`` attribute can be applied to the declaration of a variable or -a field whose type is a character array to specify that the character array is -not intended to behave like a null-terminated string. This will silence -diagnostics with code like: +a field whose type is a character pointer or character array to specify that +the buffer is not intended to behave like a null-terminated string. This will +silence diagnostics with code like: .. code-block:: c diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index a67b9995d3b54..4c7219c78c8bc 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -507,6 +507,14 @@ def note_odr_number_of_bases : Note< "class has %0 base %plural{1:class|:classes}0">; def note_odr_enumerator : Note<"enumerator %0 with value %1 here">; def note_odr_missing_enumerator : Note<"no corresponding enumerator here">; +def note_odr_incompatible_fixed_underlying_type : Note< + "enumeration %0 declared with incompatible fixed underlying types (%1 vs. " + "%2)">; +def note_odr_fixed_underlying_type : Note< + "enumeration %0 has fixed underlying type here">; +def note_odr_missing_fixed_underlying_type : Note< + "enumeration %0 missing fixed underlying type here">; + def err_odr_field_type_inconsistent : Error< "field %0 declared with incompatible types in different " "translation units (%1 vs. %2)">; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index c28a919e35d08..76f9addab47d8 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -624,6 +624,7 @@ def MissingFieldInitializers : DiagGroup<"missing-field-initializers", def ModuleLock : DiagGroup<"module-lock">; def ModuleBuild : DiagGroup<"module-build">; def ModuleImport : DiagGroup<"module-import">; +def ModuleValidation : DiagGroup<"module-validation">; def ModuleConflict : DiagGroup<"module-conflict">; def ModuleFileExtension : DiagGroup<"module-file-extension">; def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">; diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 584c8d62280bf..6494f3415b7a5 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -82,6 +82,10 @@ def remark_module_import : Remark< "importing module '%0'%select{| into '%3'}2 from '%1'">, ShowInSystemHeader, InGroup; +def remark_module_validation : Remark< + "validating %0 input files in module '%1' from '%2'">, + ShowInSystemHeader, + InGroup; def err_imported_module_not_found : Error< "module '%0' in precompiled file '%1' %select{(imported by precompiled file '%2') |}4" diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 72f23614aef11..b040181beaffd 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -147,14 +147,17 @@ FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type)) FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) -FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics) -EXTENSION(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics) +FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics && + PP.getTargetInfo().getTriple().isOSDarwin()) +FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics && + PP.getTargetInfo().getTriple().isOSDarwin()) FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls) FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns) FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination) FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls) +FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers) FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination) FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) @@ -163,7 +166,7 @@ FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT) FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa) FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel) -FEATURE(ptrauth_objc_signable_class, true) +FEATURE(ptrauth_objc_signable_class, LangOpts.PointerAuthIntrinsics) FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls) EXTENSION(swiftcc, diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 0d546cb3b8471..25f4575a54257 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces") LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication") +LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors") + LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes") LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes") @@ -496,6 +498,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign, LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C") +LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++") + LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type") #undef LANGOPT diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h index fb6dddf3ae9ce..2b920250721fc 100644 --- a/clang/include/clang/Basic/PointerAuthOptions.h +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -23,6 +23,10 @@ namespace clang { +/// Constant discriminator to be used with block descriptor pointers. The value +/// is ptrauth_string_discriminator("block_descriptor") +constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB; + /// Constant discriminator to be used with function pointers in .init_array and /// .fini_array. The value is ptrauth_string_discriminator("init_fini") constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4; @@ -223,6 +227,18 @@ struct PointerAuthOptions { /// The ABI for function addresses in .init_array and .fini_array PointerAuthSchema InitFiniPointers; + /// The ABI for block invocation function pointers. + PointerAuthSchema BlockInvocationFunctionPointers; + + /// The ABI for block object copy/destroy function pointers. + PointerAuthSchema BlockHelperFunctionPointers; + + /// The ABI for __block variable copy/destroy function pointers. + PointerAuthSchema BlockByrefHelperFunctionPointers; + + /// The ABI for pointers to block descriptors. + PointerAuthSchema BlockDescriptorPointers; + /// The ABI for Objective-C method lists. PointerAuthSchema ObjCMethodListFunctionPointers; diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td index 275bb2b9924dd..cc5ab38f8f960 100644 --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -56,34 +56,8 @@ multiclass RVVVLEFFBuiltin types> { SupportOverloading = false, UnMaskedPolicyScheme = HasPassthruOperand, ManualCodegen = [{ - { - if (IsMasked) { - // Move mask to right before vl. - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); - if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()}; - } else { - if (PolicyAttrs & RVV_VTA) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()}; - } - Value *NewVL = Ops[2]; - Ops.erase(Ops.begin() + 2); - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); - llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0}); - // Store new_vl. - clang::CharUnits Align; - if (IsMasked) - Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(E->getNumArgs()-2)->getType()); - else - Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType()); - llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1}); - Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align)); - return V; - } + return emitRVVVLEFFBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach type = types in { def : RVVBuiltin<"v", "vPCePz", type>; @@ -139,17 +113,8 @@ multiclass RVVIndexedLoad { let HasMaskedOffOperand = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - if (IsMasked) { - // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl) - std::swap(Ops[0], Ops[2]); - } else { - // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl) - std::swap(Ops[0], Ops[1]); - } - if (IsMasked) - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()}; - else - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()}; + return emitRVVVSEMaskBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> { let Name = "vsm_v"; @@ -177,17 +142,8 @@ multiclass RVVVSSEBuiltin types> { HasMaskedOffOperand = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - if (IsMasked) { - // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl) - std::swap(Ops[0], Ops[3]); - } else { - // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl) - std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); - } - if (IsMasked) - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()}; - else - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()}; + return emitRVVVSSEBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach type = types in { def : RVVBuiltin<"v", "0Petv", type>; @@ -202,17 +158,8 @@ multiclass RVVIndexedStore { let HasMaskedOffOperand = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - if (IsMasked) { - // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl) - std::swap(Ops[0], Ops[3]); - } else { - // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl) - std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); - } - if (IsMasked) - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[4]->getType()}; - else - IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), Ops[3]->getType()}; + return emitRVVIndexedStoreBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach type = TypeList in { foreach eew_list = EEWList[0-2] in { @@ -367,28 +314,8 @@ multiclass RVVPseudoUnaryBuiltin { MaskedIRName = IR # "_mask", UnMaskedPolicyScheme = HasPassthruOperand, ManualCodegen = [{ - { - if (IsMasked) { - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); - if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - } else { - if (PolicyAttrs & RVV_VTA) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - } - auto ElemTy = cast(ResultType)->getElementType(); - Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy)); - - if (IsMasked) { - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - // maskedoff, op1, op2, mask, vl, policy - IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()}; - } else { - // passthru, op1, op2, vl - IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()}; - } - break; - } + return emitRVVPseudoUnaryBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { def : RVVBuiltin<"v", "vv", type_range>; } @@ -400,32 +327,8 @@ multiclass RVVPseudoVNotBuiltin { MaskedIRName = IR # "_mask", UnMaskedPolicyScheme = HasPassthruOperand, ManualCodegen = [{ - { - if (IsMasked) { - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); - if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - } else { - if (PolicyAttrs & RVV_VTA) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - } - auto ElemTy = cast(ResultType)->getElementType(); - Ops.insert(Ops.begin() + 2, - llvm::Constant::getAllOnesValue(ElemTy)); - if (IsMasked) { - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - // maskedoff, op1, po2, mask, vl, policy - IntrinsicTypes = {ResultType, - ElemTy, - Ops[4]->getType()}; - } else { - // passthru, op1, op2, vl - IntrinsicTypes = {ResultType, - ElemTy, - Ops[3]->getType()}; - } - break; - } + return emitRVVPseudoVNotBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { def : RVVBuiltin<"v", "vv", type_range>; def : RVVBuiltin<"Uv", "UvUv", type_range>; @@ -437,13 +340,8 @@ multiclass RVVPseudoMaskBuiltin { IRName = IR, HasMasked = false, ManualCodegen = [{ - { - // op1, vl - IntrinsicTypes = {ResultType, - Ops[1]->getType()}; - Ops.insert(Ops.begin() + 1, Ops[0]); - break; - } + return emitRVVPseudoMaskBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { def : RVVBuiltin<"m", "mm", type_range>; } @@ -455,28 +353,8 @@ multiclass RVVPseudoVFUnaryBuiltin { MaskedIRName = IR # "_mask", UnMaskedPolicyScheme = HasPassthruOperand, ManualCodegen = [{ - { - if (IsMasked) { - std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); - if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - Ops.insert(Ops.begin() + 2, Ops[1]); - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - // maskedoff, op1, op2, mask, vl - IntrinsicTypes = {ResultType, - Ops[2]->getType(), - Ops.back()->getType()}; - } else { - if (PolicyAttrs & RVV_VTA) - Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); - // op1, po2, vl - IntrinsicTypes = {ResultType, - Ops[1]->getType(), Ops[2]->getType()}; - Ops.insert(Ops.begin() + 2, Ops[1]); - break; - } - break; - } + return emitRVVPseudoVFUnaryBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { def : RVVBuiltin<"v", "vv", type_range>; } @@ -490,33 +368,8 @@ multiclass RVVPseudoVWCVTBuiltin(Ops[1]->getType())->getElementType(); - Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy)); - if (IsMasked) { - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - // maskedoff, op1, op2, mask, vl, policy - IntrinsicTypes = {ResultType, - Ops[1]->getType(), - ElemTy, - Ops[4]->getType()}; - } else { - // passtru, op1, op2, vl - IntrinsicTypes = {ResultType, - Ops[1]->getType(), - ElemTy, - Ops[3]->getType()}; - } - break; - } + return emitRVVPseudoVWCVTBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach s_p = suffixes_prototypes in { def : RVVBuiltin; @@ -532,32 +385,8 @@ multiclass RVVPseudoVNCVTBuiltingetType())); - if (IsMasked) { - Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - // maskedoff, op1, xlen, mask, vl - IntrinsicTypes = {ResultType, - Ops[1]->getType(), - Ops[4]->getType(), - Ops[4]->getType()}; - } else { - // passthru, op1, xlen, vl - IntrinsicTypes = {ResultType, - Ops[1]->getType(), - Ops[3]->getType(), - Ops[3]->getType()}; - } - break; - } + return emitRVVPseudoVNCVTBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach s_p = suffixes_prototypes in { def : RVVBuiltin; @@ -575,17 +404,8 @@ let HasBuiltinAlias = false, HasVL = false, HasMasked = false, UnMaskedPolicyScheme = NonePolicy, MaskedPolicyScheme = NonePolicy, Log2LMUL = [0], IRName = "", ManualCodegen = [{ - { - LLVMContext &Context = CGM.getLLVMContext(); - llvm::MDBuilder MDHelper(Context); - - llvm::Metadata *Ops[] = {llvm::MDString::get(Context, "vlenb")}; - llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); - llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); - llvm::Function *F = - CGM.getIntrinsic(llvm::Intrinsic::read_register, {SizeTy}); - return Builder.CreateCall(F, Metadata); - } + return emitRVVVlenbBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { def vlenb : RVVBuiltin<"", "u", "i">; @@ -660,7 +480,10 @@ let HasBuiltinAlias = false, HasMasked = false, MaskedPolicyScheme = NonePolicy, Log2LMUL = [0], - ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type + ManualCodegen = [{ + return emitRVVVsetvliBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); + }] in // Set XLEN type { def vsetvli : RVVBuiltin<"", "zzKzKz", "i">; def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">; @@ -720,43 +543,10 @@ multiclass RVVUnitStridedSegLoadTuple { MaskedIRName = op # nf # "_mask", NF = nf, ManualCodegen = [{ - { - SmallVector Operands; - - bool NoPassthru = - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | - (!IsMasked && (PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; - - if (IsMasked) - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(), Ops.back()->getType()}; - else - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType()}; - - if (NoPassthru) { // Push poison into passthru - Operands.push_back(llvm::PoisonValue::get(ResultType)); - } else { // Push intrinsics operands into passthru - llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; - Operands.push_back(PassthruOperand); - } - - Operands.push_back(Ops[Offset]); // Ptr - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 1]); // VL - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - if (ReturnValue.isNull()) - return LoadValue; - else - return Builder.CreateStore(LoadValue, ReturnValue.getValue()); - } - }] in { + return emitRVVUnitStridedSegLoadTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, + IsMasked, SegInstSEW); + }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; if !not(IsFloat.val) then { @@ -784,31 +574,10 @@ multiclass RVVUnitStridedSegStoreTuple { NF = nf, HasMaskedOffOperand = false, ManualCodegen = [{ - { - // Masked - // Builtin: (mask, ptr, v_tuple, vl) - // Intrinsic: (tuple, ptr, mask, vl) - // Unmasked - // Builtin: (ptr, v_tuple, vl) - // Intrinsic: (tuple, ptr, vl) - unsigned Offset = IsMasked ? 1 : 0; - - SmallVector Operands; - Operands.push_back(Ops[Offset + 1]); // tuple - Operands.push_back(Ops[Offset]); // Ptr - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 2]); // VL - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - if (IsMasked) - IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Ops[0]->getType(), Operands.back()->getType()}; - else - IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); - } - }] in { + return emitRVVUnitStridedSegStoreTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, + IsMasked, SegInstSEW); + }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; if !not(IsFloat.val) then { @@ -835,52 +604,9 @@ multiclass RVVUnitStridedSegLoadFFTuple { MaskedIRName = op # nf # "ff_mask", NF = nf, ManualCodegen = [{ - { - SmallVector Operands; - - bool NoPassthru = - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | - (!IsMasked && (PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; - - if (IsMasked) - IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(), Ops[0]->getType()}; - else - IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType()}; - - if (NoPassthru) { // Push poison into passthru - Operands.push_back(llvm::PoisonValue::get(ResultType)); - } else { // Push intrinsics operands into passthru - llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; - Operands.push_back(PassthruOperand); - } - - Operands.push_back(Ops[Offset]); // Ptr - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 2]); // vl - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - // Get alignment from the new vl operand - clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType()); - - llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0); - - // Store new_vl - llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1); - Builder.CreateStore(V, Address(Ops[Offset + 1], V->getType(), Align)); - - if (ReturnValue.isNull()) - return ReturnTuple; - else - return Builder.CreateStore(ReturnTuple, ReturnValue.getValue()); - } + return emitRVVUnitStridedSegLoadFFTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; @@ -908,43 +634,9 @@ multiclass RVVStridedSegLoadTuple { MaskedIRName = op # nf # "_mask", NF = nf, ManualCodegen = [{ - { - SmallVector Operands; - - bool NoPassthru = - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | - (!IsMasked && (PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; - - if (IsMasked) - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType(), Ops[0]->getType()}; - else - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType()}; - - if (NoPassthru) { // Push poison into passthru - Operands.push_back(llvm::PoisonValue::get(ResultType)); - } else { // Push intrinsics operands into passthru - llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; - Operands.push_back(PassthruOperand); - } - - Operands.push_back(Ops[Offset]); // Ptr - Operands.push_back(Ops[Offset + 1]); // Stride - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 2]); // VL - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - - if (ReturnValue.isNull()) - return LoadValue; - else - return Builder.CreateStore(LoadValue, ReturnValue.getValue()); - } + return emitRVVStridedSegLoadTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; @@ -974,31 +666,9 @@ multiclass RVVStridedSegStoreTuple { HasMaskedOffOperand = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - { - // Masked - // Builtin: (mask, ptr, stride, v_tuple, vl) - // Intrinsic: (tuple, ptr, stride, mask, vl) - // Unmasked - // Builtin: (ptr, stride, v_tuple, vl) - // Intrinsic: (tuple, ptr, stride, vl) - unsigned Offset = IsMasked ? 1 : 0; - - SmallVector Operands; - Operands.push_back(Ops[Offset + 2]); // tuple - Operands.push_back(Ops[Offset]); // Ptr - Operands.push_back(Ops[Offset + 1]); // Stride - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 3]); // VL - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - if (IsMasked) - IntrinsicTypes = {Operands[0]->getType(), Operands[1]->getType(), Operands.back()->getType(), Ops[0]->getType()}; - else - IntrinsicTypes = {Operands[0]->getType(), Operands[1]->getType(), Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); - } + return emitRVVStridedSegStoreTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; @@ -1021,47 +691,9 @@ multiclass RVVIndexedSegLoadTuple { MaskedIRName = op # nf # "_mask", NF = nf, ManualCodegen = [{ - { - SmallVector Operands; - - bool NoPassthru = - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | - (!IsMasked && (PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; - - if (NoPassthru) { // Push poison into passthru - Operands.push_back(llvm::PoisonValue::get(ResultType)); - } else { // Push intrinsics operands into passthru - llvm::Value *PassthruOperand = IsMasked ? Ops[1] : Ops[0]; - Operands.push_back(PassthruOperand); - } - - Operands.push_back(Ops[Offset]); // Ptr - Operands.push_back(Ops[Offset + 1]); // Idx - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 2]); // VL - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - if (IsMasked) - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), - Ops[Offset + 1]->getType(), - Ops[0]->getType(), - Ops.back()->getType()}; - else - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), - Ops[Offset + 1]->getType(), - Ops.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); - - if (ReturnValue.isNull()) - return LoadValue; - else - return Builder.CreateStore(LoadValue, ReturnValue.getValue()); - } + return emitRVVIndexedSegLoadTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; @@ -1087,34 +719,9 @@ multiclass RVVIndexedSegStoreTuple { HasMaskedOffOperand = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - { - // Masked - // Builtin: (mask, ptr, index, v_tuple, vl) - // Intrinsic: (tuple, ptr, index, mask, vl) - // Unmasked - // Builtin: (ptr, index, v_tuple, vl) - // Intrinsic: (tuple, ptr, index, vl) - unsigned Offset = IsMasked ? 1 : 0; - - SmallVector Operands; - Operands.push_back(Ops[Offset + 2]); // tuple - Operands.push_back(Ops[Offset]); // Ptr - Operands.push_back(Ops[Offset + 1]); // Idx - if (IsMasked) - Operands.push_back(Ops[0]); - Operands.push_back(Ops[Offset + 3]); // VL - Operands.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); - - if (IsMasked) - IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Ops[Offset + 1]->getType(), - Ops[0]->getType(), - Operands.back()->getType()}; - else - IntrinsicTypes = {Operands[0]->getType(), Ops[Offset]->getType(), Ops[Offset + 1]->getType(), - Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); - } + return emitRVVIndexedSegStoreTupleBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); }] in { defvar T = "(Tuple:" # nf # ")"; def : RVVBuiltin; @@ -1355,37 +962,8 @@ defm vssub : RVVSignedBinBuiltinSet; let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - Operands.push_back(Ops[Offset + 2]); // vxrm - Operands.push_back(Ops[Offset + 3]); // vl - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(), Ops.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVAveragingBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); } }] in { // 12.2. Vector Single-Width Averaging Add and Subtract @@ -1404,38 +982,8 @@ let ManualCodegen = [{ let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - Operands.push_back(Ops[Offset + 2]); // vxrm - Operands.push_back(Ops[Offset + 3]); // vl - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), - Ops.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVNarrowingClipBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); } }] in { // 12.5. Vector Narrowing Fixed-Point Clip Instructions @@ -1459,47 +1007,8 @@ enum __RISCV_FRM { let UnMaskedPolicyScheme = HasPassthruOperand in { let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - bool HasRoundModeOp = IsMasked ? - (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : - (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); - - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 2]); // frm - Operands.push_back(Ops[Offset + 3]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset + 1]->getType(), - Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVFloatingPointBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); } }] in { let HasFRMRoundModeOp = true in { @@ -1536,47 +1045,9 @@ let ManualCodegen = [{ let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - bool HasRoundModeOp = IsMasked ? - (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : - (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); - - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 2]); // frm - Operands.push_back(Ops[Offset + 3]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), - Ops.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVWideningFloatingPointBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); } }] in { let HasFRMRoundModeOp = true in { @@ -1618,39 +1089,8 @@ let ManualCodegen = [{ let UnMaskedPolicyScheme = HasPolicyOperand in { let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) - - SmallVector Operands; - bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; - - unsigned Offset = IsMasked ? 2 : 1; - - Operands.push_back(Ops[IsMasked ? 1 : 0]); // passthrough - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 2]); // frm - Operands.push_back(Ops[Offset + 3]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } - - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), - Operands.back()->getType()}; - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - - return Builder.CreateCall(F, Operands, ""); + return emitRVVFMABuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); } }] in { let HasFRMRoundModeOp = 1 in { @@ -1677,39 +1117,8 @@ let ManualCodegen = [{ let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) - - SmallVector Operands; - bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; - - unsigned Offset = IsMasked ? 2 : 1; - - Operands.push_back(Ops[IsMasked ? 1 : 0]); // passthrough - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 2]); // frm - Operands.push_back(Ops[Offset + 3]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } - - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[Offset + 1]->getType(), - Operands.back()->getType()}; - - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - - return Builder.CreateCall(F, Operands, ""); + return emitRVVWideningFMABuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); } }] in { let HasFRMRoundModeOp = 1 in { @@ -1747,45 +1156,8 @@ let ManualCodegen = [{ let UnMaskedPolicyScheme = HasPassthruOperand in { let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, round_mode, vl) - // Masked: (passthru, op0, mask, frm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - bool HasRoundModeOp = IsMasked ? - (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) : - (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); - - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 1]); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 1]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 1]); // vl - } - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVFloatingUnaryBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); } }] in { let HasFRMRoundModeOp = 1 in { @@ -1947,45 +1319,8 @@ def vfwcvtbf16_f_f_v : RVVConvBuiltin<"Fw", "Fwv", "y", "vfwcvtbf16_f">; let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, frm, vl) - // Masked: (passthru, op0, mask, frm, vl, policy) - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - bool HasRoundModeOp = IsMasked ? - (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) : - (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); - - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 1]); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 1]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 1]); // vl - } - - if (IsMasked) - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), - Operands.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVFloatingConvBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); } }] in { let HasFRMRoundModeOp = 1 in { @@ -2151,44 +1486,9 @@ defm vfredmax : RVVFloatingReductionBuiltin; defm vfredmin : RVVFloatingReductionBuiltin; let ManualCodegen = [{ { - // LLVM intrinsic - // Unmasked: (passthru, op0, op1, round_mode, vl) - // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) - - SmallVector Operands; - bool HasMaskedOff = !( - (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || - (!IsMasked && PolicyAttrs & RVV_VTA)); - bool HasRoundModeOp = IsMasked ? - (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) : - (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); - - unsigned Offset = IsMasked ? - (HasMaskedOff ? 2 : 1) : (HasMaskedOff ? 1 : 0); - - if (!HasMaskedOff) - Operands.push_back(llvm::PoisonValue::get(ResultType)); - else - Operands.push_back(Ops[IsMasked ? 1 : 0]); - - Operands.push_back(Ops[Offset]); // op0 - Operands.push_back(Ops[Offset + 1]); // op1 - - if (IsMasked) - Operands.push_back(Ops[0]); // mask - - if (HasRoundModeOp) { - Operands.push_back(Ops[Offset + 2]); // frm - Operands.push_back(Ops[Offset + 3]); // vl - } else { - Operands.push_back(ConstantInt::get(Ops[Offset + 2]->getType(), 7)); // frm - Operands.push_back(Ops[Offset + 2]); // vl - } - - IntrinsicTypes = {ResultType, Ops[Offset]->getType(), - Ops.back()->getType()}; - llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); - return Builder.CreateCall(F, Operands, ""); + return emitRVVFloatingReductionBuiltin( + this, E, ReturnValue, ResultType, ID, Ops, PolicyAttrs, IsMasked, + SegInstSEW); } }] in { let HasFRMRoundModeOp = 1 in { @@ -2346,37 +1646,8 @@ let HasMasked = false, let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vreinterpret_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - if (ResultType->isIntOrIntVectorTy(1) || - Ops[0]->getType()->isIntOrIntVectorTy(1)) { - assert(isa(ResultType) && - isa(Ops[0]->getType())); - - LLVMContext &Context = CGM.getLLVMContext(); - ScalableVectorType *Boolean64Ty = - ScalableVectorType::get(llvm::Type::getInt1Ty(Context), 64); - - if (ResultType->isIntOrIntVectorTy(1)) { - // Casting from m1 vector integer -> vector boolean - // Ex: - // --(bitcast)--------> - // --(vector_extract)-> - llvm::Value *BitCast = Builder.CreateBitCast(Ops[0], Boolean64Ty); - return Builder.CreateExtractVector(ResultType, BitCast, - ConstantInt::get(Int64Ty, 0)); - } else { - // Casting from vector boolean -> m1 vector integer - // Ex: - // --(vector_insert)-> - // --(bitcast)-------> - llvm::Value *Boolean64Val = - Builder.CreateInsertVector(Boolean64Ty, - llvm::PoisonValue::get(Boolean64Ty), - Ops[0], - ConstantInt::get(Int64Ty, 0)); - return Builder.CreateBitCast(Boolean64Val, ResultType); - } - } - return Builder.CreateBitCast(Ops[0], ResultType); + return emitRVVReinterpretBuiltin(this, E, ReturnValue, ResultType, ID, + Ops, PolicyAttrs, IsMasked, SegInstSEW); }] in { // Reinterpret between different type under the same SEW and LMUL def vreinterpret_i_u : RVVBuiltin<"Uvv", "vUv", "csil", "v">; @@ -2502,25 +1773,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vget_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - { - auto *VecTy = cast(ResultType); - if (auto *OpVecTy = dyn_cast(Ops[0]->getType())) { - unsigned MaxIndex = OpVecTy->getMinNumElements() / VecTy->getMinNumElements(); - assert(isPowerOf2_32(MaxIndex)); - // Mask to only valid indices. - Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty()); - Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1); - Ops[1] = Builder.CreateMul(Ops[1], - ConstantInt::get(Ops[1]->getType(), - VecTy->getMinNumElements())); - return Builder.CreateExtractVector(ResultType, Ops[0], Ops[1]); - } - - return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_extract, - {ResultType, Ops[0]->getType()}, - {Ops[0], Builder.CreateTrunc(Ops[1], - Builder.getInt32Ty())}); - } + return emitRVVGetBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach dst_lmul = ["(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in { def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilxfdy", dst_lmul # "v">; @@ -2535,25 +1789,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { let Name = "vset_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ - { - if (auto *ResVecTy = dyn_cast(ResultType)) { - auto *VecTy = cast(Ops[2]->getType()); - unsigned MaxIndex = ResVecTy->getMinNumElements() / VecTy->getMinNumElements(); - assert(isPowerOf2_32(MaxIndex)); - // Mask to only valid indices. - Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty()); - Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1); - Ops[1] = Builder.CreateMul(Ops[1], - ConstantInt::get(Ops[1]->getType(), - VecTy->getMinNumElements())); - return Builder.CreateInsertVector(ResultType, Ops[0], Ops[2], Ops[1]); - } - - return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert, - {ResultType, Ops[2]->getType()}, - {Ops[0], Ops[2], - Builder.CreateTrunc(Ops[1],Builder.getInt32Ty())}); - } + return emitRVVSetBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in { def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "v" # dst_lmul # "vKzv", "csilxfdy">; @@ -2571,26 +1808,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { MaskedPolicyScheme = NonePolicy, SupportOverloading = false, ManualCodegen = [{ - { - llvm::Value *ReturnVector = llvm::PoisonValue::get(ResultType); - auto *VecTy = cast(Ops[0]->getType()); - for (unsigned I = 0, N = Ops.size(); I < N; ++I) { - if (isa(ResultType)) { - llvm::Value *Idx = ConstantInt::get(Builder.getInt64Ty(), - VecTy->getMinNumElements() * I); - ReturnVector = - Builder.CreateInsertVector(ResultType, ReturnVector, Ops[I], Idx); - } else { - llvm::Value *Idx = ConstantInt::get(Builder.getInt32Ty(), I); - ReturnVector = - Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert, - {ResultType, Ops[I]->getType()}, - {ReturnVector, Ops[I], Idx}); - } - - } - return ReturnVector; - } + return emitRVVCreateBuiltin(this, E, ReturnValue, ResultType, ID, Ops, + PolicyAttrs, IsMasked, SegInstSEW); }] in { // Since the vcreate_v uses LFixedLog2LMUL, setting the Log2LMUL to [-3] can diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index e7c7e9d93fe21..958d0d05ade29 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -990,6 +990,13 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Pass to the linker">, MetaVarName<"">, Group; +def Xthinlto_distributor_EQ : CommaJoined<["-"], "Xthinlto-distributor=">, + Flags<[LinkOption]>, + Visibility<[ClangOption, CLOption]>, + HelpText<"Pass to the ThinLTO distributor process. Can be specified " + "multiple times or with comma-separated values.">, + MetaVarName<"">, + Group; def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">, Visibility<[ClangOption, FlangOption]>, HelpText<"Pass to the offload linkers or the ones identified by -">, @@ -1910,6 +1917,14 @@ defm bounds_safety : BoolFOption< BothFlags<[], [CC1Option], " experimental bounds safety extension for C">>; +defm lifetime_safety : BoolFOption< + "experimental-lifetime-safety", + LangOpts<"EnableLifetimeSafety">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[], [CC1Option], + " experimental lifetime safety for C++">>; + defm addrsig : BoolFOption<"addrsig", CodeGenOpts<"Addrsig">, DefaultFalse, PosFlag, @@ -4249,7 +4264,12 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, HelpText<"Do not assume that any loop is finite.">, Visibility<[ClangOption, CC1Option]>; - +def fthinlto_distributor_EQ : Joined<["-"], "fthinlto-distributor=">, + Group, + HelpText<"Path to the ThinLTO distributor process. If specified, " + "ThinLTO backend compilations will be distributed by LLD">, + MetaVarName<"">, + Visibility<[ClangOption, CLOption]>; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, @@ -4507,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening", defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">; defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">; defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">; +defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index b4f2a87fe7e83..f0d0000c42a9b 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4694,6 +4694,13 @@ struct FormatStyle { /// /// \endcode bool AfterIfMacros; + /// If ``true``, put a space between alternative operator ``not`` and the + /// opening parenthesis. + /// \code + /// true: false: + /// return not (a || b); vs. return not(a || b); + /// \endcode + bool AfterNot; /// If ``true``, put a space between operator overloading and opening /// parentheses. /// \code @@ -4742,9 +4749,9 @@ struct FormatStyle { : AfterControlStatements(false), AfterForeachMacros(false), AfterFunctionDeclarationName(false), AfterFunctionDefinitionName(false), AfterIfMacros(false), - AfterOverloadedOperator(false), AfterPlacementOperator(true), - AfterRequiresInClause(false), AfterRequiresInExpression(false), - BeforeNonEmptyParentheses(false) {} + AfterNot(false), AfterOverloadedOperator(false), + AfterPlacementOperator(true), AfterRequiresInClause(false), + AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {} bool operator==(const SpaceBeforeParensCustom &Other) const { return AfterControlStatements == Other.AfterControlStatements && @@ -4753,6 +4760,7 @@ struct FormatStyle { Other.AfterFunctionDeclarationName && AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName && AfterIfMacros == Other.AfterIfMacros && + AfterNot == Other.AfterNot && AfterOverloadedOperator == Other.AfterOverloadedOperator && AfterPlacementOperator == Other.AfterPlacementOperator && AfterRequiresInClause == Other.AfterRequiresInClause && diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h index 06971ff87ab96..423f2ffe2f852 100644 --- a/clang/include/clang/Lex/Lexer.h +++ b/clang/include/clang/Lex/Lexer.h @@ -143,9 +143,6 @@ class Lexer : public PreprocessorLexer { /// True if this is the first time we're lexing the input file. bool IsFirstTimeLexingFile; - /// True if current lexing token is the first pp-token. - bool IsFirstPPToken; - // NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n', // it also points to '\n.' const char *NewLinePtr; diff --git a/clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h b/clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h new file mode 100644 index 0000000000000..9ab3c6a528a1a --- /dev/null +++ b/clang/include/clang/Lex/NoTrivialPPDirectiveTracer.h @@ -0,0 +1,310 @@ +//===--- NoTrivialPPDirectiveTracer.h ---------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the NoTrivialPPDirectiveTracer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H +#define LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H + +#include "clang/Lex/PPCallbacks.h" + +namespace clang { +class Preprocessor; + +/// Consider the following code: +/// +/// # 1 __FILE__ 1 3 +/// export module a; +/// +/// According to the wording in +/// [P1857R3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1857r3.html): +/// +/// A module directive may only appear as the first preprocessing tokens in a +/// file (excluding the global module fragment.) +/// +/// and the wording in +/// [[cpp.pre]](https://eel.is/c++draft/cpp.pre#nt:module-file): +/// module-file: +/// pp-global-module-fragment[opt] pp-module group[opt] +/// pp-private-module-fragment[opt] +/// +/// `#` is the first pp-token in the translation unit, and it was rejected by +/// clang, but they really should be exempted from this rule. The goal is to not +/// allow any preprocessor conditionals or most state changes, but these don't +/// fit that. +/// +/// State change would mean most semantically observable preprocessor state, +/// particularly anything that is order dependent. Global flags like being a +/// system header/module shouldn't matter. +/// +/// We should exempt a brunch of directives, even though it violates the current +/// standard wording. +/// +/// This class used to trace 'no-trivial' pp-directives in main file, which may +/// change the preprocessing state. +/// +/// FIXME: Once the wording of the standard is revised, we need to follow the +/// wording of the standard. Currently this is just a workaround +class NoTrivialPPDirectiveTracer : public PPCallbacks { + Preprocessor &PP; + + /// Whether preprocessing main file. We only focus on the main file. + bool InMainFile = true; + + /// Whether one or more conditional, include or other 'no-trivial' + /// pp-directives has seen before. + bool SeenNoTrivialPPDirective = false; + + void setSeenNoTrivialPPDirective(); + +public: + NoTrivialPPDirectiveTracer(Preprocessor &P) : PP(P) {} + + bool hasSeenNoTrivialPPDirective() const; + + /// Callback invoked whenever the \p Lexer moves to a different file for + /// lexing. Unlike \p FileChanged line number directives and other related + /// pragmas do not trigger callbacks to \p LexedFileChanged. + /// + /// \param FID The \p FileID that the \p Lexer moved to. + /// + /// \param Reason Whether the \p Lexer entered a new file or exited one. + /// + /// \param FileType The \p CharacteristicKind of the file the \p Lexer moved + /// to. + /// + /// \param PrevFID The \p FileID the \p Lexer was using before the change. + /// + /// \param Loc The location where the \p Lexer entered a new file from or the + /// location that the \p Lexer moved into after exiting a file. + void LexedFileChanged(FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID, + SourceLocation Loc) override; + + /// Callback invoked whenever an embed directive has been processed, + /// regardless of whether the embed will actually find a file. + /// + /// \param HashLoc The location of the '#' that starts the embed directive. + /// + /// \param FileName The name of the file being included, as written in the + /// source code. + /// + /// \param IsAngled Whether the file name was enclosed in angle brackets; + /// otherwise, it was enclosed in quotes. + /// + /// \param File The actual file that may be included by this embed directive. + /// + /// \param Params The parameters used by the directive. + void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled, + OptionalFileEntryRef File, + const LexEmbedParametersResult &Params) override { + setSeenNoTrivialPPDirective(); + } + + /// Callback invoked whenever an inclusion directive of + /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless + /// of whether the inclusion will actually result in an inclusion. + /// + /// \param HashLoc The location of the '#' that starts the inclusion + /// directive. + /// + /// \param IncludeTok The token that indicates the kind of inclusion + /// directive, e.g., 'include' or 'import'. + /// + /// \param FileName The name of the file being included, as written in the + /// source code. + /// + /// \param IsAngled Whether the file name was enclosed in angle brackets; + /// otherwise, it was enclosed in quotes. + /// + /// \param FilenameRange The character range of the quotes or angle brackets + /// for the written file name. + /// + /// \param File The actual file that may be included by this inclusion + /// directive. + /// + /// \param SearchPath Contains the search path which was used to find the file + /// in the file system. If the file was found via an absolute include path, + /// SearchPath will be empty. For framework includes, the SearchPath and + /// RelativePath will be split up. For example, if an include of "Some/Some.h" + /// is found via the framework path + /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be + /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be + /// "Some.h". + /// + /// \param RelativePath The path relative to SearchPath, at which the include + /// file was found. This is equal to FileName except for framework includes. + /// + /// \param SuggestedModule The module suggested for this header, if any. + /// + /// \param ModuleImported Whether this include was translated into import of + /// \p SuggestedModule. + /// + /// \param FileType The characteristic kind, indicates whether a file or + /// directory holds normal user code, system code, or system code which is + /// implicitly 'extern "C"' in C++ mode. + /// + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, + StringRef FileName, bool IsAngled, + CharSourceRange FilenameRange, + OptionalFileEntryRef File, StringRef SearchPath, + StringRef RelativePath, const Module *SuggestedModule, + bool ModuleImported, + SrcMgr::CharacteristicKind FileType) override { + setSeenNoTrivialPPDirective(); + } + + /// Callback invoked whenever there was an explicit module-import + /// syntax. + /// + /// \param ImportLoc The location of import directive token. + /// + /// \param Path The identifiers (and their locations) of the module + /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Imported The imported module; can be null if importing failed. + /// + void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, + const Module *Imported) override { + setSeenNoTrivialPPDirective(); + } + + /// Callback invoked when the end of the main file is reached. + /// + /// No subsequent callbacks will be made. + void EndOfMainFile() override { setSeenNoTrivialPPDirective(); } + + /// Callback invoked when start reading any pragma directive. + void PragmaDirective(SourceLocation Loc, + PragmaIntroducerKind Introducer) override {} + + /// Called by Preprocessor::HandleMacroExpandedIdentifier when a + /// macro invocation is found. + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range, const MacroArgs *Args) override; + + /// Hook called whenever a macro definition is seen. + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever a macro \#undef is seen. + /// \param MacroNameTok The active Token + /// \param MD A MacroDefinition for the named macro. + /// \param Undef New MacroDirective if the macro was defined, null otherwise. + /// + /// MD is released immediately following this callback. + void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, + const MacroDirective *Undef) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever the 'defined' operator is seen. + /// \param MD The MacroDirective if the name was a macro, null otherwise. + void Defined(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#if is seen. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param ConditionValue The evaluated value of the condition. + /// + // FIXME: better to pass in a list (or tree!) of Tokens. + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#elif is seen. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param ConditionValue The evaluated value of the condition. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. + // FIXME: better to pass in a list (or tree!) of Tokens. + void Elif(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue, SourceLocation IfLoc) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#ifdef is seen. + /// \param Loc the source location of the directive. + /// \param MacroNameTok Information on the token being tested. + /// \param MD The MacroDefinition if the name was a macro, null otherwise. + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#elifdef branch is taken. + /// \param Loc the source location of the directive. + /// \param MacroNameTok Information on the token being tested. + /// \param MD The MacroDefinition if the name was a macro, null otherwise. + void Elifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + setSeenNoTrivialPPDirective(); + } + /// Hook called whenever an \#elifdef is skipped. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. + // FIXME: better to pass in a list (or tree!) of Tokens. + void Elifdef(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#ifndef is seen. + /// \param Loc the source location of the directive. + /// \param MacroNameTok Information on the token being tested. + /// \param MD The MacroDefiniton if the name was a macro, null otherwise. + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#elifndef branch is taken. + /// \param Loc the source location of the directive. + /// \param MacroNameTok Information on the token being tested. + /// \param MD The MacroDefinition if the name was a macro, null otherwise. + void Elifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + setSeenNoTrivialPPDirective(); + } + /// Hook called whenever an \#elifndef is skipped. + /// \param Loc the source location of the directive. + /// \param ConditionRange The SourceRange of the expression being tested. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. + // FIXME: better to pass in a list (or tree!) of Tokens. + void Elifndef(SourceLocation Loc, SourceRange ConditionRange, + SourceLocation IfLoc) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#else is seen. + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. + void Else(SourceLocation Loc, SourceLocation IfLoc) override { + setSeenNoTrivialPPDirective(); + } + + /// Hook called whenever an \#endif is seen. + /// \param Loc the source location of the directive. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. + void Endif(SourceLocation Loc, SourceLocation IfLoc) override { + setSeenNoTrivialPPDirective(); + } +}; + +} // namespace clang + +#endif // LLVM_CLANG_LEX_NO_TRIVIAL_PPDIRECTIVE_TRACER_H diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 4d82e20e5d4f3..e90564a9739a5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -82,6 +82,7 @@ class PreprocessorLexer; class PreprocessorOptions; class ScratchBuffer; class TargetInfo; +class NoTrivialPPDirectiveTracer; namespace Builtin { class Context; @@ -353,6 +354,11 @@ class Preprocessor { /// First pp-token source location in current translation unit. SourceLocation FirstPPTokenLoc; + /// A preprocessor directive tracer to trace whether the preprocessing + /// state changed. These changes would mean most semantically observable + /// preprocessor state, particularly anything that is order dependent. + NoTrivialPPDirectiveTracer *DirTracer = nullptr; + /// A position within a C++20 import-seq. class StdCXXImportSeq { public: @@ -609,6 +615,8 @@ class Preprocessor { return State == NamedModuleImplementation && !getName().contains(':'); } + bool isNotAModuleDecl() const { return State == NotAModuleDecl; } + StringRef getName() const { assert(isNamedModule() && "Can't get name from a non named module"); return Name; @@ -3087,6 +3095,10 @@ class Preprocessor { bool setDeserializedSafeBufferOptOutMap( const SmallVectorImpl &SrcLocSeqs); + /// Whether we've seen pp-directives which may have changed the preprocessing + /// state. + bool hasSeenNoTrivialPPDirective() const; + private: /// Helper functions to forward lexing to the actual lexer. They all share the /// same signature. diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index fc43e72593b94..d9dc5a562d802 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -86,12 +86,12 @@ class Token { // macro stringizing or charizing operator. CommaAfterElided = 0x200, // The comma following this token was elided (MS). IsEditorPlaceholder = 0x400, // This identifier is a placeholder. - - IsReinjected = 0x800, // A phase 4 token that was produced before and - // re-added, e.g. via EnterTokenStream. Annotation - // tokens are *not* reinjected. - FirstPPToken = 0x1000, // This token is the first pp token in the - // translation unit. + IsReinjected = 0x800, // A phase 4 token that was produced before and + // re-added, e.g. via EnterTokenStream. Annotation + // tokens are *not* reinjected. + HasSeenNoTrivialPPDirective = + 0x1000, // Whether we've seen any 'no-trivial' pp-directives before + // current position. }; tok::TokenKind getKind() const { return Kind; } @@ -321,8 +321,9 @@ class Token { /// lexer uses identifier tokens to represent placeholders. bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); } - /// Returns true if this token is the first pp-token. - bool isFirstPPToken() const { return getFlag(FirstPPToken); } + bool hasSeenNoTrivialPPDirective() const { + return getFlag(HasSeenNoTrivialPPDirective); + } }; /// Information about the conditional stack (\#if directives) diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 9135ff949eeab..a70335bef9dd4 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -350,11 +350,6 @@ class Sema; LLVM_PREFERRED_TYPE(bool) unsigned BindsToRvalue : 1; - /// Whether this was an identity conversion with qualification - /// conversion for the implicit object argument. - LLVM_PREFERRED_TYPE(bool) - unsigned IsImplicitObjectArgumentQualificationConversion : 1; - /// Whether this binds an implicit object argument to a /// non-static member function without a ref-qualifier. LLVM_PREFERRED_TYPE(bool) @@ -453,11 +448,11 @@ class Sema; #endif return true; } + if (!C.hasSameType(getFromType(), getToType(2))) + return false; if (BindsToRvalue && IsLvalueReference) return false; - if (IsImplicitObjectArgumentQualificationConversion) - return C.hasSameUnqualifiedType(getFromType(), getToType(2)); - return C.hasSameType(getFromType(), getToType(2)); + return true; } ImplicitConversionRank getRank() const; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b331acbe606b7..7b0be368d67f9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9836,7 +9836,7 @@ class Sema final : public SemaBase { SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path, ModuleIdPath Partition, ModuleImportState &ImportState, - bool IntroducerIsFirstPPToken); + bool SeenNoTrivialPPDirective); /// The parser has processed a global-module-fragment declaration that begins /// the definition of the global module fragment of the current module unit. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0499a81cd5231..862f1d5741c5b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1725,6 +1725,9 @@ ASTContext::PointerAuthContent ASTContext::findPointerAuthContent(QualType T) { assert(isPointerAuthenticationAvailable()); T = T.getCanonicalType(); + if (T->isDependentType()) + return PointerAuthContent::None; + if (T.hasAddressDiscriminatedPointerAuth()) return PointerAuthContent::AddressDiscriminatedData; const RecordDecl *RD = T->getAsRecordDecl(); @@ -3032,7 +3035,7 @@ bool ASTContext::hasUniqueObjectRepresentations( return true; } - // All other pointers (except __ptrauth pointers) are unique. + // All other pointers are unique. if (Ty->isPointerType()) return !Ty.hasAddressDiscriminatedPointerAuth(); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 3aa6b37844103..25d19a3dcd486 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -456,7 +456,9 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context, const Decl *D1, const Decl *D2, const Decl *PrimaryDecl = nullptr) { // If either declaration has an attribute on it, we treat the declarations - // as not being structurally equivalent. + // as not being structurally equivalent unless both declarations are implicit + // (ones generated by the compiler like __NSConstantString_tag). + // // FIXME: this should be handled on a case-by-case basis via tablegen in // Attr.td. There are multiple cases to consider: one declaration with the // attribute, another without it; different attribute syntax|spellings for @@ -468,7 +470,7 @@ CheckStructurallyEquivalentAttributes(StructuralEquivalenceContext &Context, D1Attr = *D1->getAttrs().begin(); if (D2->hasAttrs()) D2Attr = *D2->getAttrs().begin(); - if (D1Attr || D2Attr) { + if ((D1Attr || D2Attr) && !D1->isImplicit() && !D2->isImplicit()) { const auto *DiagnoseDecl = cast(PrimaryDecl ? PrimaryDecl : D2); Context.Diag2(DiagnoseDecl->getLocation(), diag::warn_odr_tag_type_with_attributes) @@ -873,7 +875,29 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, else if (T1->getTypeClass() == Type::FunctionNoProto && T2->getTypeClass() == Type::FunctionProto) TC = Type::FunctionNoProto; - else + else if (Context.LangOpts.C23 && !Context.StrictTypeSpelling && + (T1->getTypeClass() == Type::Enum || + T2->getTypeClass() == Type::Enum)) { + // In C23, if not being strict about token equivalence, we need to handle + // the case where one type is an enumeration and the other type is an + // integral type. + // + // C23 6.7.3.3p16: The enumerated type is compatible with the underlying + // type of the enumeration. + // + // Treat the enumeration as its underlying type and use the builtin type + // class comparison. + if (T1->getTypeClass() == Type::Enum) { + T1 = T1->getAs()->getDecl()->getIntegerType(); + if (!T2->isBuiltinType() || T1.isNull()) // Sanity check + return false; + } else if (T2->getTypeClass() == Type::Enum) { + T2 = T2->getAs()->getDecl()->getIntegerType(); + if (!T1->isBuiltinType() || T2.isNull()) // Sanity check + return false; + } + TC = Type::Builtin; + } else return false; } @@ -2067,6 +2091,48 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, !CheckStructurallyEquivalentAttributes(Context, D1, D2)) return false; + // In C23, if one enumeration has a fixed underlying type, the other shall + // have a compatible fixed underlying type (6.2.7). + if (Context.LangOpts.C23) { + if (D1->isFixed() != D2->isFixed()) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2) + << (&Context.FromCtx != &Context.ToCtx); + Context.Diag1(D1->getLocation(), + D1->isFixed() + ? diag::note_odr_fixed_underlying_type + : diag::note_odr_missing_fixed_underlying_type) + << D1; + Context.Diag2(D2->getLocation(), + D2->isFixed() + ? diag::note_odr_fixed_underlying_type + : diag::note_odr_missing_fixed_underlying_type) + << D2; + } + return false; + } + if (D1->isFixed()) { + assert(D2->isFixed() && "enums expected to have fixed underlying types"); + if (!IsStructurallyEquivalent(Context, D1->getIntegerType(), + D2->getIntegerType())) { + if (Context.Complain) { + Context.Diag2(D2->getLocation(), + Context.getApplicableDiagnostic( + diag::err_odr_tag_type_inconsistent)) + << Context.ToCtx.getTypeDeclType(D2) + << (&Context.FromCtx != &Context.ToCtx); + Context.Diag2(D2->getLocation(), + diag::note_odr_incompatible_fixed_underlying_type) + << D2 << D2->getIntegerType() << D1->getIntegerType(); + } + return false; + } + } + } + llvm::SmallVector D1Enums, D2Enums; auto CopyEnumerators = [](auto &&Range, llvm::SmallVectorImpl &Cont) { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 4514965009793..64895f4fb9d45 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1448,6 +1448,13 @@ void CXXRecordDecl::addedMember(Decl *D) { data().StructuralIfLiteral = false; } + // If this type contains any address discriminated values we should + // have already indicated that the only special member functions that + // can possibly be trivial are the default constructor and destructor. + if (T.hasAddressDiscriminatedPointerAuth()) + data().HasTrivialSpecialMembers &= + SMF_DefaultConstructor | SMF_Destructor; + // C++14 [meta.unary.prop]p4: // T is a class type [...] with [...] no non-static data members other // than subobjects of zero size diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 419dd5dbdc695..bfecae972940b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4441,7 +4441,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } } else if (!IsAccess) { return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); - } else if (IsConstant && Info.checkingPotentialConstantExpression() && + } else if ((IsConstant || BaseType->isReferenceType()) && + Info.checkingPotentialConstantExpression() && BaseType->isLiteralType(Info.Ctx) && !VD->hasDefinition()) { // This variable might end up being constexpr. Don't diagnose it yet. } else if (IsConstant) { @@ -4478,9 +4479,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, // a null BaseVal. Any constexpr-unknown variable seen here is an error: // we can't access a constexpr-unknown object. if (!BaseVal) { - Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1) - << AK << VD; - Info.Note(VD->getLocation(), diag::note_declared_at); + if (!Info.checkingPotentialConstantExpression()) { + Info.FFDiag(E, diag::note_constexpr_access_unknown_variable, 1) + << AK << VD; + Info.Note(VD->getLocation(), diag::note_declared_at); + } return CompleteObject(); } } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast()) { @@ -7906,8 +7909,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc, // so its layout is unspecified. For now, we'll simply treat these cases // as unsupported (this should only be possible with OpenCL bool vectors // whose element count isn't a multiple of the byte size). - Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector) - << QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth(); + if (Info) + Info->FFDiag(Loc, diag::note_constexpr_bit_cast_invalid_vector) + << QualType(VTy, 0) << EltSize << NElts << Ctx.getCharWidth(); return false; } @@ -7916,8 +7920,9 @@ static bool checkBitCastConstexprEligibilityType(SourceLocation Loc, // The layout for x86_fp80 vectors seems to be handled very inconsistently // by both clang and LLVM, so for now we won't allow bit_casts involving // it in a constexpr context. - Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type) - << EltTy; + if (Info) + Info->FFDiag(Loc, diag::note_constexpr_bit_cast_unsupported_type) + << EltTy; return false; } } @@ -10929,10 +10934,6 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, bool ZeroInit = E->requiresZeroInitialization(); if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { - // If we've already performed zero-initialization, we're already done. - if (Result.hasValue()) - return true; - if (ZeroInit) return ZeroInitialization(E, T); @@ -14478,12 +14479,6 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; - // If we have Unknown pointers we should fail if they are not global values. - if (!(IsGlobalLValue(LHSValue.getLValueBase()) && - IsGlobalLValue(RHSValue.getLValueBase())) && - (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown)) - return false; - // Reject differing bases from the normal codepath; we special-case // comparisons to null. if (!HasSameBase(LHSValue, RHSValue)) { @@ -14545,6 +14540,10 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, (LHSValue.Base && isZeroSized(RHSValue))) return DiagComparison( diag::note_constexpr_pointer_comparison_zero_sized); + if (LHSValue.AllowConstexprUnknown || RHSValue.AllowConstexprUnknown) + return DiagComparison( + diag::note_constexpr_pointer_comparison_unspecified); + // FIXME: Verify both variables are live. return Success(CmpResult::Unequal, E); } @@ -14565,7 +14564,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch( - getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); + LHSValue.Base.isNull() ? QualType() + : getType(LHSValue.Base).getNonReferenceType(), + LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices @@ -14609,7 +14610,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E, // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && IsRelational) { - QualType BaseTy = getType(LHSValue.Base); + QualType BaseTy = getType(LHSValue.Base).getNonReferenceType(); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e5a1ab2ff8906..bd3dd983bca7e 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2715,6 +2715,11 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { return false; QualType CanonicalType = getTypePtr()->CanonicalType; + + // Any type that is, or contains, address discriminated data is never POD. + if (const_cast(Context).containsAddressDiscriminatedPointerAuth(CanonicalType)) + return false; + switch (CanonicalType->getTypeClass()) { // Everything not explicitly mentioned is not POD. default: @@ -2773,6 +2778,11 @@ bool QualType::isTrivialType(const ASTContext &Context) const { if (CanonicalType->isDependentType()) return false; + // Any type that is, or contains, address discriminated data is never a + // trivial type. + if (const_cast(Context).containsAddressDiscriminatedPointerAuth(CanonicalType)) + return false; + // C++0x [basic.types]p9: // Scalar types, trivial class types, arrays of such types, and // cv-qualified versions of these types are collectively called trivial @@ -2870,6 +2880,12 @@ bool QualType::isBitwiseCloneableType(const ASTContext &Context) const { if (CanonicalType->isIncompleteType()) return false; + + // Any type that is, or contains, address discriminated data is never + // bitwise clonable. + if (const_cast(Context).containsAddressDiscriminatedPointerAuth(CanonicalType)) + return false; + const auto *RD = CanonicalType->getAsRecordDecl(); // struct/union/class if (!RD) return true; @@ -3115,6 +3131,10 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { if (BaseTy->isIncompleteType()) return false; + // Any type that is, or contains, address discriminated data is non-POD. + if (const_cast(Context).containsAddressDiscriminatedPointerAuth(*this)) + return false; + // As an extension, Clang treats vector types as Scalar types. if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index 80e7c8eff671a..dadb0b757a2c8 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1331,7 +1331,7 @@ void ThreadSafetyAnalyzer::addLock(FactSet &FSet, FSet.removeLock(FactMan, NegC); } else { - if (inCurrentScope(*Entry) && !Entry->asserted()) + if (inCurrentScope(*Entry) && !Entry->asserted() && !Entry->reentrant()) Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(), NegC.toString(), Entry->loc()); } diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index af1111a863308..5d11578893c66 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -769,6 +769,9 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); + case llvm::Triple::OpenBSD: + return std::make_unique>(Triple, + Opts); default: return std::make_unique(Triple, Opts); } diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index f6915df1520b7..8e29bb745734b 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -461,6 +461,8 @@ LoongArchTargetInfo::parseTargetAttr(StringRef Features) const { case AttrFeatureKind::Feature: Ret.Features.push_back("+" + Value.str()); + if (Value == "lasx") + Ret.Features.push_back("+lsx"); break; } } diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 35501ed44ccd7..e199df32f56ee 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -129,7 +129,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { LongWidth = LongAlign = 32; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; PointerWidth = PointerAlign = 32; - PtrDiffType = SignedInt; + PtrDiffType = IntPtrType = SignedInt; SizeType = UnsignedInt; SuitableAlign = 64; } @@ -155,7 +155,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { IntMaxType = Int64Type; LongWidth = LongAlign = 64; PointerWidth = PointerAlign = 64; - PtrDiffType = SignedLong; + PtrDiffType = IntPtrType = SignedLong; SizeType = UnsignedLong; } @@ -165,7 +165,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { IntMaxType = Int64Type; LongWidth = LongAlign = 32; PointerWidth = PointerAlign = 32; - PtrDiffType = SignedInt; + PtrDiffType = IntPtrType = SignedInt; SizeType = UnsignedInt; } diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 30d861a7ca605..c1a68f464e831 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -174,6 +174,9 @@ class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo DefineStd(Builder, "unix", Opts); if (this->HasFloat128) Builder.defineMacro("__FLOAT128__"); + + if (Opts.C11) + Builder.defineMacro("__STDC_NO_THREADS__"); } public: @@ -496,6 +499,7 @@ class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo { case llvm::Triple::sparcv9: this->MCountName = "_mcount"; break; + case llvm::Triple::loongarch64: case llvm::Triple::riscv64: break; } diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index ebc59c92f4c24..a7be080695ed3 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -649,6 +649,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_32TargetInfo : public X86_32TargetInfo { : X86_32TargetInfo(Triple, Opts) { this->WCharType = TargetInfo::UnsignedShort; this->WIntType = TargetInfo::UnsignedInt; + this->UseMicrosoftManglingForC = true; DoubleAlign = LongLongAlign = 64; resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-" "i128:128-f80:32-n8:16:32-a:0:32-S32", @@ -986,6 +987,7 @@ class LLVM_LIBRARY_VISIBILITY CygwinX86_64TargetInfo : public X86_64TargetInfo { : X86_64TargetInfo(Triple, Opts) { this->WCharType = TargetInfo::UnsignedShort; this->WIntType = TargetInfo::UnsignedInt; + this->UseMicrosoftManglingForC = true; } void getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index a748ddaa110a5..4e7f3561ac049 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -176,6 +176,11 @@ class Address { static Address invalid() { return Address(nullptr); } bool isValid() const { return Pointer.getPointer() != nullptr; } + llvm::Value *getPointerIfNotSigned() const { + assert(isValid() && "pointer isn't valid"); + return !isSigned() ? Pointer.getPointer() : nullptr; + } + /// This function is used in situations where the caller is doing some sort of /// opaque "laundering" of the pointer. void replaceBasePointer(llvm::Value *P) { diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 1aba841eb5fc2..c1f5b983f7233 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, // Optional copy/dispose helpers. bool hasInternalHelper = false; if (blockInfo.NeedsCopyDispose) { + auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers; // copy_func_helper_decl llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo); - elements.add(copyHelper); + elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType()); // destroy_func_decl llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo); - elements.add(disposeHelper); + elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType()); if (cast(copyHelper->stripPointerCasts()) ->hasInternalLinkage() || @@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); info.CanBeGlobal = true; return; - } - else if (C.getLangOpts().ObjC && - CGM.getLangOpts().getGC() == LangOptions::NonGC) + } else if (C.getLangOpts().ObjC && + CGM.getLangOpts().getGC() == LangOptions::NonGC) info.HasCapturedVariableLayout = true; if (block->doesNotEscape()) @@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL; - auto GenVoidPtrTy = + llvm::PointerType *GenVoidPtrTy = IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy; LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default; auto GenVoidPtrSize = CharUnits::fromQuantity( @@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { : CGM.getNSConcreteStackBlock(); isa = blockISA; - // Build the block descriptor. - descriptor = buildBlockDescriptor(CGM, blockInfo); - // Compute the initial on-stack block flags. if (!CGM.getCodeGenOpts().DisableBlockSignatureString) flags = BLOCK_HAS_SIGNATURE; @@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { flags |= BLOCK_USE_STRET; if (blockInfo.NoEscape) flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL; + + // Build the block descriptor. + descriptor = buildBlockDescriptor(CGM, blockInfo); } auto projectField = [&](unsigned index, const Twine &name) -> Address { @@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()), getIntSize(), "block.align"); } - addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); - if (!IsOpenCL) - addHeaderField(descriptor, getPointerSize(), "block.descriptor"); - else if (auto *Helper = - CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + + if (!IsOpenCL) { + llvm::Value *blockFnPtr = + llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy); + QualType type = blockInfo.getBlockExpr() + ->getType() + ->castAs() + ->getPointeeType(); + addSignedHeaderField( + blockFnPtr, + CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers, + GlobalDecl(), type, getPointerSize(), "block.invoke"); + + addSignedHeaderField( + descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers, + GlobalDecl(), type, getPointerSize(), "block.descriptor"); + } else if (auto *Helper = + CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { + addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) { addHeaderField( I.first, @@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { CGM.getDataLayout().getTypeAllocSize(I.first->getType())), I.second); } - } + } else + addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); } // Finally, capture all the values into the block. @@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, ASTContext &Ctx = getContext(); CallArgList Args; + llvm::Value *FuncPtr = nullptr; + if (getLangOpts().OpenCL) { // For OpenCL, BlockPtr is already casted to generic block literal. @@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, if (!isa(E->getCalleeDecl())) Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee()); else { - llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2); + FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2); Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr, getPointerAlign()); } @@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, BlockPtr = Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal"); // Get pointer to the block invoke function - llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3); + FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3); // First argument is a block literal casted to a void pointer BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy); @@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); // Prepare the callee. - CGCallee Callee(CGCalleeInfo(), Func); + CGPointerAuthInfo PointerAuth; + if (auto &AuthSchema = + CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) { + assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo"); + PointerAuth = + EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType); + } + + CGCallee Callee(CGCalleeInfo(), Func, PointerAuth); // And call the block. return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke); @@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, bool IsOpenCL = CGM.getLangOpts().OpenCL; bool IsWindows = CGM.getTarget().getTriple().isOSWindows(); + auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth; if (!IsOpenCL) { // isa if (IsWindows) fields.addNullPointer(CGM.Int8PtrPtrTy); else fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(), - CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers, - GlobalDecl(), QualType()); + CGOPointerAuth.ObjCIsaPointers, GlobalDecl(), + QualType()); // __flags BlockFlags flags = BLOCK_IS_GLOBAL; @@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, } // Function - fields.add(blockFn); + if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) { + QualType FnType = blockInfo.getBlockExpr() + ->getType() + ->castAs() + ->getPointeeType(); + fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType); + } else + fields.add(blockFn); if (!IsOpenCL) { // Descriptor - fields.add(buildBlockDescriptor(CGM, blockInfo)); + llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo); + fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers, + GlobalDecl(), QualType()); } else if (auto *Helper = CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) { @@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - if (auto *I = - cast_or_null(dstField.getBasePointer())) + if (auto *I = cast_or_null( + dstField.getPointerIfNotSigned())) I->eraseFromParent(); } break; @@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { unsigned nextHeaderIndex = 0; CharUnits nextHeaderOffset; auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize, - const Twine &name) { + const Twine &name, bool isFunction = false) { auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name); + if (isFunction) { + if (auto &Schema = CGM.getCodeGenOpts() + .PointerAuth.BlockByrefHelperFunctionPointers) { + auto PointerAuth = EmitPointerAuthInfo( + Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType()); + value = EmitPointerAuthSign(PointerAuth, value); + } + } Builder.CreateStore(value, fieldAddr); nextHeaderIndex++; @@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getIntSize(), "byref.size"); if (helpers) { - storeHeaderField(helpers->CopyHelper, getPointerSize(), - "byref.copyHelper"); + storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper", + /*isFunction=*/true); storeHeaderField(helpers->DisposeHelper, getPointerSize(), - "byref.disposeHelper"); + "byref.disposeHelper", /*isFunction=*/true); } if (ByRefHasLifetime && HasByrefExtendedLayout) { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c8c3d6b20c496..5344a9710d642 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4787,19 +4787,6 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup { } }; -struct DisableDebugLocationUpdates { - CodeGenFunction &CGF; - bool disabledDebugInfo; - DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) { - if ((disabledDebugInfo = isa(E) && CGF.getDebugInfo())) - CGF.disableDebugInfo(); - } - ~DisableDebugLocationUpdates() { - if (disabledDebugInfo) - CGF.enableDebugInfo(); - } -}; - } // end anonymous namespace RValue CallArg::getRValue(CodeGenFunction &CGF) const { @@ -4836,7 +4823,9 @@ void CodeGenFunction::EmitWritebacks(const CallArgList &args) { void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, QualType type) { - DisableDebugLocationUpdates Dis(*this, E); + std::optional Dis; + if (isa(E)) + Dis.emplace(*this); if (const ObjCIndirectCopyRestoreExpr *CRE = dyn_cast(E)) { assert(getLangOpts().ObjCAutoRefCount); @@ -6229,3 +6218,12 @@ RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr, return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot); return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot); } + +DisableDebugLocationUpdates::DisableDebugLocationUpdates(CodeGenFunction &CGF) + : CGF(CGF) { + CGF.disableDebugInfo(); +} + +DisableDebugLocationUpdates::~DisableDebugLocationUpdates() { + CGF.enableDebugInfo(); +} diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 0b4e3f9cb0365..17b2ce558f711 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -457,6 +457,12 @@ inline FnInfoOpts &operator&=(FnInfoOpts &A, FnInfoOpts B) { return A; } +struct DisableDebugLocationUpdates { + CodeGenFunction &CGF; + DisableDebugLocationUpdates(CodeGenFunction &CGF); + ~DisableDebugLocationUpdates(); +}; + } // end namespace CodeGen } // end namespace clang diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 0fc488e98aaf0..117ef3d16e21b 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -707,11 +707,15 @@ struct GetReturnObjectManager { Builder.CreateStore(Builder.getFalse(), GroActiveFlag); GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl); - auto *GroAlloca = dyn_cast_or_null( - GroEmission.getOriginalAllocatedAddress().getPointer()); - assert(GroAlloca && "expected alloca to be emitted"); - GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame, - llvm::MDNode::get(CGF.CGM.getLLVMContext(), {})); + + if (!GroVarDecl->isNRVOVariable()) { + // NRVO variables don't have allocas and won't have the same issue. + auto *GroAlloca = dyn_cast_or_null( + GroEmission.getOriginalAllocatedAddress().getPointer()); + assert(GroAlloca && "expected alloca to be emitted"); + GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame, + llvm::MDNode::get(CGF.CGM.getLLVMContext(), {})); + } // Remember the top of EHStack before emitting the cleanup. auto old_top = CGF.EHStack.stable_begin(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index f97c7b6445984..ec28bd259e8e1 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -170,6 +170,10 @@ void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions) return; + llvm::DISubprogram *SP = KeyInstruction->getFunction()->getSubprogram(); + if (!SP || !SP->getKeyInstructionsEnabled()) + return; + addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1); llvm::Instruction *BackupI = @@ -2641,7 +2645,8 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { // existing information in the DWARF. The type is assumed to be 'void *'. void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD) { - if (!CGM.getTarget().getCXXABI().isItaniumFamily()) + if (!CGM.getTarget().getCXXABI().isItaniumFamily() || + CGM.getTarget().getTriple().isOSBinFormatCOFF()) return; ASTContext &Context = CGM.getContext(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c768807572f..b5debd93b0f61 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3314,7 +3314,14 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { auto *FD = LambdaCaptureFields.lookup(BD); return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); } - return EmitLValue(BD->getBinding()); + // Suppress debug location updates when visiting the binding, since the + // binding may emit instructions that would otherwise be associated with the + // binding itself, rather than the expression referencing the binding. (this + // leads to jumpy debug stepping behavior where the location/debugger jump + // back to the binding declaration, then back to the expression referencing + // the binding) + DisableDebugLocationUpdates D(*this); + return EmitLValue(BD->getBinding(), NotKnownNonNull); } // We can form DeclRefExprs naming GUID declarations when reconstituting diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 359e30cb8f5cd..912b1d72c7e23 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2313,7 +2313,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, bool IsExact = !IsDynamicCastToVoid && CGM.getCodeGenOpts().OptimizationLevel > 0 && DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() && - CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy); + CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy) && + !getLangOpts().PointerAuthCalls; // C++ [expr.dynamic.cast]p4: // If the value of v is a null pointer value in the pointer case, the result diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 715bd392f59f7..0cc468ca3ab7e 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -873,8 +873,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, for (const BaseInfo &Base : Bases) { bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl; - Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase, - VTableClass, Offset + Base.Offset); + if (!Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase, + VTableClass, Offset + Base.Offset)) + return false; } } @@ -1620,7 +1621,7 @@ llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) { if (CE->isGLValue()) RetType = CGM.getContext().getLValueReferenceType(RetType); - return emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType); + return tryEmitAbstract(CE->getAPValueResult(), RetType); } llvm::Constant * diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index e0650067b9547..1a8c6f015bda1 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { if (HaveInsertPoint()) EmitStopPoint(&S); + ApplyAtomGroup Grp(getDebugInfo()); EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel())); } void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { + ApplyAtomGroup Grp(getDebugInfo()); if (const LabelDecl *Target = S.getConstantTarget()) { EmitBranchThroughCleanup(getJumpDestForLabel(Target)); return; @@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { cast(IndGotoBB->begin())->addIncoming(V, CurBB); EmitBranch(IndGotoBB); + if (CurBB && CurBB->getTerminator()) + addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr); } void CodeGenFunction::EmitIfStmt(const IfStmt &S) { @@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, llvm::ConstantAsMetadata::get(Loc))); } + // Make inline-asm calls Key for the debug info feature Key Instructions. + CGF.addInstToNewSourceAtom(&Result, nullptr); + if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent()) // Conservatively, mark all inline asm blocks in CUDA or OpenCL as // convergent (meaning, they may call an intrinsically convergent op, such @@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, } } + ApplyAtomGroup Grp(CGF.getDebugInfo()); LValue Dest = ResultRegDests[i]; // ResultTypeRequiresCast elements correspond to the first // ResultTypeRequiresCast.size() elements of RegResults. @@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S, unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]); Address A = Dest.getAddress().withElementType(ResultRegTypes[i]); if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) { - Builder.CreateStore(Tmp, A); + llvm::StoreInst *S = Builder.CreateStore(Tmp, A); + CGF.addInstToCurrentSourceAtom(S, S->getValueOperand()); continue; } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 6c32c98cec011..f5ac9f387c641 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -727,7 +727,7 @@ class CodeGenFunction : public CodeGenTypeCache { }; /// Header for data within LifetimeExtendedCleanupStack. - struct LifetimeExtendedCleanupHeader { + struct alignas(uint64_t) LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. unsigned Size; /// The kind of cleanup to push. @@ -949,7 +949,8 @@ class CodeGenFunction : public CodeGenTypeCache { LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size + (Header.IsConditional ? sizeof(ActiveFlag) : 0)); - static_assert(sizeof(Header) % alignof(T) == 0, + static_assert((alignof(LifetimeExtendedCleanupHeader) == alignof(T)) && + (alignof(T) == alignof(RawAddress)), "Cleanup will be allocated on misaligned address"); char *Buffer = &LifetimeExtendedCleanupStack[OldSize]; new (Buffer) LifetimeExtendedCleanupHeader(Header); diff --git a/clang/lib/CodeGen/EHScopeStack.h b/clang/lib/CodeGen/EHScopeStack.h index ed11dc2bb05d7..54f6ceaa52b95 100644 --- a/clang/lib/CodeGen/EHScopeStack.h +++ b/clang/lib/CodeGen/EHScopeStack.h @@ -143,7 +143,7 @@ class EHScopeStack { /// /// Cleanup implementations should generally be declared in an /// anonymous namespace. - class Cleanup { + class alignas(uint64_t) Cleanup { // Anchor the construction vtable. virtual void anchor(); diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp index 89e3f6f203df3..99194cd7fbb38 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -20,6 +20,951 @@ using namespace clang; using namespace CodeGen; using namespace llvm; +// The 0th bit simulates the `vta` of RVV +// The 1st bit simulates the `vma` of RVV +static constexpr unsigned RVV_VTA = 0x1; +static constexpr unsigned RVV_VMA = 0x2; + +// RISC-V Vector builtin helper functions are marked NOINLINE to prevent +// excessive inlining in CodeGenFunction::EmitRISCVBuiltinExpr's large switch +// statement, which would significantly increase compilation time. +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVVLEFFBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + // Move mask to right before vl. + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + IntrinsicTypes = {ResultType, Ops[4]->getType(), Ops[2]->getType()}; + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + IntrinsicTypes = {ResultType, Ops[3]->getType(), Ops[1]->getType()}; + } + Value *NewVL = Ops[2]; + Ops.erase(Ops.begin() + 2); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); + llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0}); + // Store new_vl. + clang::CharUnits Align; + if (IsMasked) + Align = CGM.getNaturalPointeeTypeAlignment( + E->getArg(E->getNumArgs() - 2)->getType()); + else + Align = CGM.getNaturalPointeeTypeAlignment(E->getArg(1)->getType()); + llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {1}); + Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align)); + return V; +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVVSSEBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, + // mask, vl) + std::swap(Ops[0], Ops[3]); + } else { + // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl) + std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); + } + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedStoreBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + // Builtin: (mask, ptr, index, value, vl). + // Intrinsic: (value, ptr, index, mask, vl) + std::swap(Ops[0], Ops[3]); + } else { + // Builtin: (ptr, index, value, vl). + // Intrinsic: (value, ptr, index, vl) + std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); + } + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), + Ops[4]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVPseudoUnaryBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } + auto ElemTy = cast(ResultType)->getElementType(); + Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy)); + if (IsMasked) { + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + // maskedoff, op1, op2, mask, vl, policy + IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()}; + } else { + // passthru, op1, op2, vl + IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()}; + } + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVPseudoVNotBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } + auto ElemTy = cast(ResultType)->getElementType(); + Ops.insert(Ops.begin() + 2, llvm::Constant::getAllOnesValue(ElemTy)); + if (IsMasked) { + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + // maskedoff, op1, po2, mask, vl, policy + IntrinsicTypes = {ResultType, ElemTy, Ops[4]->getType()}; + } else { + // passthru, op1, op2, vl + IntrinsicTypes = {ResultType, ElemTy, Ops[3]->getType()}; + } + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVPseudoMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // op1, vl + IntrinsicTypes = {ResultType, Ops[1]->getType()}; + Ops.insert(Ops.begin() + 1, Ops[0]); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVPseudoVFUnaryBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + Ops.insert(Ops.begin() + 2, Ops[1]); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + // maskedoff, op1, op2, mask, vl + IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops.back()->getType()}; + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + // op1, po2, vl + IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()}; + Ops.insert(Ops.begin() + 2, Ops[1]); + } + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVPseudoVWCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } + auto ElemTy = cast(Ops[1]->getType())->getElementType(); + Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(ElemTy)); + if (IsMasked) { + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + // maskedoff, op1, op2, mask, vl, policy + IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[4]->getType()}; + } else { + // passtru, op1, op2, vl + IntrinsicTypes = {ResultType, Ops[1]->getType(), ElemTy, Ops[3]->getType()}; + } + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVPseudoVNCVTBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } else { + if (PolicyAttrs & RVV_VTA) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + } + Ops.insert(Ops.begin() + 2, + llvm::Constant::getNullValue(Ops.back()->getType())); + if (IsMasked) { + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + // maskedoff, op1, xlen, mask, vl + IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[4]->getType(), + Ops[4]->getType()}; + } else { + // passthru, op1, xlen, vl + IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType(), + Ops[3]->getType()}; + } + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVVlenbBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + LLVMContext &Context = CGM.getLLVMContext(); + llvm::MDBuilder MDHelper(Context); + llvm::Metadata *OpsMD[] = {llvm::MDString::get(Context, "vlenb")}; + llvm::MDNode *RegName = llvm::MDNode::get(Context, OpsMD); + llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); + llvm::Function *F = + CGM.getIntrinsic(llvm::Intrinsic::read_register, {CGF->SizeTy}); + return Builder.CreateCall(F, Metadata); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVVsetvliBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::Function *F = CGM.getIntrinsic(ID, {ResultType}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVVSEMaskBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + if (IsMasked) { + // Builtin: (mask, ptr, value, vl). + // Intrinsic: (value, ptr, mask, vl) + std::swap(Ops[0], Ops[2]); + } else { + // Builtin: (ptr, value, vl). + // Intrinsic: (value, ptr, vl) + std::swap(Ops[0], Ops[1]); + } + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + if (IsMasked) + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops[0]->getType(), + Ops.back()->getType()}; + else + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), + Ops.back()->getType()}; + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if (NoPassthru) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); + if (ReturnValue.isNull()) + return LoadValue; + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegStoreTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // Masked + // Builtin: (mask, ptr, v_tuple, vl) + // Intrinsic: (tuple, ptr, mask, vl, SegInstSEW) + // Unmasked + // Builtin: (ptr, v_tuple, vl) + // Intrinsic: (tuple, ptr, vl, SegInstSEW) + if (IsMasked) + std::swap(Ops[0], Ops[2]); + else + std::swap(Ops[0], Ops[1]); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVUnitStridedSegLoadFFTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + if (IsMasked) + IntrinsicTypes = {ResultType, Ops.back()->getType(), Ops[Offset]->getType(), + Ops[0]->getType()}; + else + IntrinsicTypes = {ResultType, Ops.back()->getType(), + Ops[Offset]->getType()}; + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if (NoPassthru) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + Value *NewVL = Ops[2]; + Ops.erase(Ops.begin() + 2); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); + // Get alignment from the new vl operand + clang::CharUnits Align = + CGM.getNaturalPointeeTypeAlignment(E->getArg(Offset + 1)->getType()); + llvm::Value *ReturnTuple = Builder.CreateExtractValue(LoadValue, 0); + // Store new_vl + llvm::Value *V = Builder.CreateExtractValue(LoadValue, 1); + Builder.CreateStore(V, Address(NewVL, V->getType(), Align)); + if (ReturnValue.isNull()) + return ReturnTuple; + return Builder.CreateStore(ReturnTuple, ReturnValue.getValue()); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegLoadTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + unsigned Offset = IsMasked ? NoPassthru ? 1 : 2 : NoPassthru ? 0 : 1; + if (IsMasked) + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), Ops.back()->getType(), + Ops[0]->getType()}; + else + IntrinsicTypes = {ResultType, Ops[Offset]->getType(), + Ops.back()->getType()}; + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if (NoPassthru) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); + if (ReturnValue.isNull()) + return LoadValue; + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVStridedSegStoreTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // Masked + // Builtin: (mask, ptr, stride, v_tuple, vl) + // Intrinsic: (tuple, ptr, stride, mask, vl, SegInstSEW) + // Unmasked + // Builtin: (ptr, stride, v_tuple, vl) + // Intrinsic: (tuple, ptr, stride, vl, SegInstSEW) + if (IsMasked) + std::swap(Ops[0], Ops[3]); + else + std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[4]->getType(), + Ops[3]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[3]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVAveragingBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, + // policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic( + ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVNarrowingClipBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, vxrm, vl, + // policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = + CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(), + Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingPointBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = + IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) + : (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic( + ID, {ResultType, Ops[2]->getType(), Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVWideningFloatingPointBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = + IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) + : (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = + CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(), + Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegLoadTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + + bool NoPassthru = + (IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) | + (!IsMasked && (PolicyAttrs & RVV_VTA)); + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1); + if (NoPassthru) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + + if (IsMasked) + IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType(), Ops[4]->getType()}; + else + IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + llvm::Value *LoadValue = Builder.CreateCall(F, Ops, ""); + + if (ReturnValue.isNull()) + return LoadValue; + return Builder.CreateStore(LoadValue, ReturnValue.getValue()); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVIndexedSegStoreTupleBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // Masked + // Builtin: (mask, ptr, index, v_tuple, vl) + // Intrinsic: (tuple, ptr, index, mask, vl, SegInstSEW) + // Unmasked + // Builtin: (ptr, index, v_tuple, vl) + // Intrinsic: (tuple, ptr, index, vl, SegInstSEW) + + if (IsMasked) + std::swap(Ops[0], Ops[3]); + else + std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); + + Ops.push_back(ConstantInt::get(Ops.back()->getType(), SegInstSEW)); + + if (IsMasked) + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType(), Ops[4]->getType()}; + else + IntrinsicTypes = {Ops[0]->getType(), Ops[1]->getType(), Ops[2]->getType(), + Ops[3]->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVFMABuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode, + // vl, policy) + // Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm, + // vl, policy) + + bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic( + ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVWideningFMABuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (vector_in, vector_in/scalar_in, vector_in, round_mode, vl, + // policy) Masked: (vector_in, vector_in/scalar_in, vector_in, mask, frm, + // vl, policy) + + bool HasRoundModeOp = IsMasked ? Ops.size() == 6 : Ops.size() == 5; + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 4); + + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = + CGM.getIntrinsic(ID, {ResultType, Ops[1]->getType(), Ops[2]->getType(), + Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingUnaryBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, round_mode, vl) + // Masked: (passthru, op0, mask, frm, vl, policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = + IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) + : (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + IntrinsicTypes = {ResultType, Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingConvBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, frm, vl) + // Masked: (passthru, op0, mask, frm, vl, policy) + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = + IsMasked ? (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4) + : (HasMaskedOff ? Ops.size() == 4 : Ops.size() == 3); + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + if (IsMasked) + Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + + llvm::Function *F = CGM.getIntrinsic( + ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value *emitRVVFloatingReductionBuiltin( + CodeGenFunction *CGF, const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Type *ResultType, Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + llvm::SmallVector IntrinsicTypes; + // LLVM intrinsic + // Unmasked: (passthru, op0, op1, round_mode, vl) + // Masked: (passthru, vector_in, vector_in/scalar_in, mask, frm, vl, policy) + + bool HasMaskedOff = + !((IsMasked && (PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA)) || + (!IsMasked && PolicyAttrs & RVV_VTA)); + bool HasRoundModeOp = + IsMasked ? (HasMaskedOff ? Ops.size() == 6 : Ops.size() == 5) + : (HasMaskedOff ? Ops.size() == 5 : Ops.size() == 4); + + if (!HasRoundModeOp) + Ops.insert(Ops.end() - 1, + ConstantInt::get(Ops.back()->getType(), 7)); // frm + + if (IsMasked) + std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 2); + + if (!HasMaskedOff) + Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType)); + + llvm::Function *F = CGM.getIntrinsic( + ID, {ResultType, Ops[1]->getType(), Ops.back()->getType()}); + return Builder.CreateCall(F, Ops, ""); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVReinterpretBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto &CGM = CGF->CGM; + + if (ResultType->isIntOrIntVectorTy(1) || + Ops[0]->getType()->isIntOrIntVectorTy(1)) { + assert(isa(ResultType) && + isa(Ops[0]->getType())); + + LLVMContext &Context = CGM.getLLVMContext(); + ScalableVectorType *Boolean64Ty = + ScalableVectorType::get(llvm::Type::getInt1Ty(Context), 64); + + if (ResultType->isIntOrIntVectorTy(1)) { + // Casting from m1 vector integer -> vector boolean + // Ex: + // --(bitcast)--------> + // --(vector_extract)-> + llvm::Value *BitCast = Builder.CreateBitCast(Ops[0], Boolean64Ty); + return Builder.CreateExtractVector(ResultType, BitCast, + ConstantInt::get(CGF->Int64Ty, 0)); + } else { + // Casting from vector boolean -> m1 vector integer + // Ex: + // --(vector_insert)-> + // --(bitcast)-------> + llvm::Value *Boolean64Val = Builder.CreateInsertVector( + Boolean64Ty, llvm::PoisonValue::get(Boolean64Ty), Ops[0], + ConstantInt::get(CGF->Int64Ty, 0)); + return Builder.CreateBitCast(Boolean64Val, ResultType); + } + } + return Builder.CreateBitCast(Ops[0], ResultType); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVGetBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + auto *VecTy = cast(ResultType); + if (auto *OpVecTy = dyn_cast(Ops[0]->getType())) { + unsigned MaxIndex = + OpVecTy->getMinNumElements() / VecTy->getMinNumElements(); + assert(isPowerOf2_32(MaxIndex)); + // Mask to only valid indices. + Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty()); + Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1); + Ops[1] = + Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(), + VecTy->getMinNumElements())); + return Builder.CreateExtractVector(ResultType, Ops[0], Ops[1]); + } + + return Builder.CreateIntrinsic( + Intrinsic::riscv_tuple_extract, {ResultType, Ops[0]->getType()}, + {Ops[0], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())}); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVSetBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + if (auto *ResVecTy = dyn_cast(ResultType)) { + auto *VecTy = cast(Ops[2]->getType()); + unsigned MaxIndex = + ResVecTy->getMinNumElements() / VecTy->getMinNumElements(); + assert(isPowerOf2_32(MaxIndex)); + // Mask to only valid indices. + Ops[1] = Builder.CreateZExt(Ops[1], Builder.getInt64Ty()); + Ops[1] = Builder.CreateAnd(Ops[1], MaxIndex - 1); + Ops[1] = + Builder.CreateMul(Ops[1], ConstantInt::get(Ops[1]->getType(), + VecTy->getMinNumElements())); + return Builder.CreateInsertVector(ResultType, Ops[0], Ops[2], Ops[1]); + } + + return Builder.CreateIntrinsic( + Intrinsic::riscv_tuple_insert, {ResultType, Ops[2]->getType()}, + {Ops[0], Ops[2], Builder.CreateTrunc(Ops[1], Builder.getInt32Ty())}); +} + +static LLVM_ATTRIBUTE_NOINLINE Value * +emitRVVCreateBuiltin(CodeGenFunction *CGF, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Type *ResultType, + Intrinsic::ID ID, SmallVectorImpl &Ops, + int PolicyAttrs, bool IsMasked, unsigned SegInstSEW) { + auto &Builder = CGF->Builder; + llvm::Value *ReturnVector = llvm::PoisonValue::get(ResultType); + auto *VecTy = cast(Ops[0]->getType()); + for (unsigned I = 0, N = Ops.size(); I < N; ++I) { + if (isa(ResultType)) { + llvm::Value *Idx = ConstantInt::get(Builder.getInt64Ty(), + VecTy->getMinNumElements() * I); + ReturnVector = + Builder.CreateInsertVector(ResultType, ReturnVector, Ops[I], Idx); + } else { + llvm::Value *Idx = ConstantInt::get(Builder.getInt32Ty(), I); + ReturnVector = Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert, + {ResultType, Ops[I]->getType()}, + {ReturnVector, Ops[I], Idx}); + } + } + return ReturnVector; +} + Value *CodeGenFunction::EmitRISCVCpuInit() { llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {VoidPtrTy}, false); llvm::FunctionCallee Func = @@ -180,10 +1125,6 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, } Intrinsic::ID ID = Intrinsic::not_intrinsic; - // The 0th bit simulates the `vta` of RVV - // The 1st bit simulates the `vma` of RVV - constexpr unsigned RVV_VTA = 0x1; - constexpr unsigned RVV_VMA = 0x2; int PolicyAttrs = 0; bool IsMasked = false; // This is used by segment load/store to determine it's llvm type. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 277d69daf493c..af711c14d4edb 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -75,6 +75,8 @@ TargetCodeGenInfo::~TargetCodeGenInfo() = default; // If someone can figure out a general rule for this, that would be great. // It's probably just doomed to be platform-dependent, though. unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { + if (getABIInfo().getContext().getLangOpts().hasSEHExceptions()) + return getABIInfo().getDataLayout().getPointerSizeInBits() > 32 ? 64 : 48; // Verified for: // x86-64 FreeBSD, Linux, Darwin // x86-32 FreeBSD, Linux, Darwin diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 9642196b78c63..0461f121d76c9 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -8,6 +8,7 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include using namespace clang; using namespace clang::CodeGen; @@ -109,7 +110,8 @@ class SparcV9ABIInfo : public ABIInfo { SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} private: - ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const; + ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit, + unsigned &RegOffset) const; void computeInfo(CGFunctionInfo &FI) const override; RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override; @@ -222,127 +224,114 @@ class SparcV9ABIInfo : public ABIInfo { }; } // end anonymous namespace -ABIArgInfo -SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { +ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit, + unsigned &RegOffset) const { if (Ty->isVoidType()) return ABIArgInfo::getIgnore(); - uint64_t Size = getContext().getTypeSize(Ty); + auto &Context = getContext(); + auto &VMContext = getVMContext(); + + uint64_t Size = Context.getTypeSize(Ty); + unsigned Alignment = Context.getTypeAlign(Ty); + bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0); // Anything too big to fit in registers is passed with an explicit indirect // pointer / sret pointer. - if (Size > SizeLimit) + if (Size > SizeLimit) { + RegOffset += 1; return getNaturalAlignIndirect( Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); + } // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); // Integer types smaller than a register are extended. - if (Size < 64 && Ty->isIntegerType()) + if (Size < 64 && Ty->isIntegerType()) { + RegOffset += 1; return ABIArgInfo::getExtend(Ty); + } if (const auto *EIT = Ty->getAs()) - if (EIT->getNumBits() < 64) + if (EIT->getNumBits() < 64) { + RegOffset += 1; return ABIArgInfo::getExtend(Ty); + } // Other non-aggregates go in registers. - if (!isAggregateTypeForABI(Ty)) + if (!isAggregateTypeForABI(Ty)) { + RegOffset += Size / 64; return ABIArgInfo::getDirect(); + } // If a C++ object has either a non-trivial copy constructor or a non-trivial // destructor, it is passed with an explicit indirect pointer / sret pointer. - if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { + RegOffset += 1; return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), RAA == CGCXXABI::RAA_DirectInMemory); + } // This is a small aggregate type that should be passed in registers. // Build a coercion type from the LLVM struct type. llvm::StructType *StrTy = dyn_cast(CGT.ConvertType(Ty)); - if (!StrTy) + if (!StrTy) { + RegOffset += Size / 64; return ABIArgInfo::getDirect(); + } - CoerceBuilder CB(getVMContext(), getDataLayout()); + CoerceBuilder CB(VMContext, getDataLayout()); CB.addStruct(0, StrTy); // All structs, even empty ones, should take up a register argument slot, // so pin the minimum struct size to one bit. CB.pad(llvm::alignTo( std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)), 64)); + RegOffset += CB.Size / 64; + + // If we're dealing with overaligned structs we may need to add a padding in + // the front, to preserve the correct register-memory mapping. + // + // See SCD 2.4.1, pages 3P-11 and 3P-12. + llvm::Type *Padding = + NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr; + RegOffset += NeedPadding ? 1 : 0; // Try to use the original type for coercion. llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType(); - if (CB.InReg) - return ABIArgInfo::getDirectInReg(CoerceTy); - else - return ABIArgInfo::getDirect(CoerceTy); + ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding); + AAI.setInReg(CB.InReg); + return AAI; } RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const { - ABIArgInfo AI = classifyType(Ty, 16 * 8); - llvm::Type *ArgTy = CGT.ConvertType(Ty); - if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) - AI.setCoerceToType(ArgTy); - CharUnits SlotSize = CharUnits::fromQuantity(8); + auto TInfo = getContext().getTypeInfoInChars(Ty); - CGBuilderTy &Builder = CGF.Builder; - Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"), - getVAListElementType(CGF), SlotSize); - llvm::Type *ArgPtrTy = CGF.UnqualPtrTy; - - auto TypeInfo = getContext().getTypeInfoInChars(Ty); - - Address ArgAddr = Address::invalid(); - CharUnits Stride; - switch (AI.getKind()) { - case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - case ABIArgInfo::InAlloca: - llvm_unreachable("Unsupported ABI kind for va_arg"); - - case ABIArgInfo::Extend: { - Stride = SlotSize; - CharUnits Offset = SlotSize - TypeInfo.Width; - ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend"); - break; - } - - case ABIArgInfo::Direct: { - auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType()); - Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize); - ArgAddr = Addr; - break; - } - - case ABIArgInfo::Indirect: - case ABIArgInfo::IndirectAliased: - Stride = SlotSize; - ArgAddr = Addr.withElementType(ArgPtrTy); - ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy, - TypeInfo.Align); - break; + // Zero-sized types have a width of one byte for parameter passing purposes. + TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1)); - case ABIArgInfo::Ignore: - return Slot.asRValue(); - } - - // Update VAList. - Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); - - return CGF.EmitLoadOfAnyValue( - CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot); + // Arguments bigger than 2*SlotSize bytes are passed indirectly. + return emitVoidPtrVAArg(CGF, VAListAddr, Ty, + /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo, + SlotSize, + /*AllowHigherAlign=*/true, Slot); } void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8); + unsigned RetOffset = 0; + ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset); + FI.getReturnInfo() = RetType; + + // Indirect returns will have its pointer passed as an argument. + unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0; for (auto &I : FI.arguments()) - I.info = classifyType(I.type, 16 * 8); + I.info = classifyType(I.type, 16 * 8, ArgOffset); } namespace { diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 3f9b808b2722e..07a3ae925f96d 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -837,17 +837,30 @@ void ToolChain::addFortranRuntimeLibs(const ArgList &Args, void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) const { - // Default to the /../lib directory. This works fine on the - // platforms that we have tested so far. We will probably have to re-fine - // this in the future. In particular, on some platforms, we may need to use - // lib64 instead of lib. + auto AddLibSearchPathIfExists = [&](const Twine &Path) { + // Linker may emit warnings about non-existing directories + if (!llvm::sys::fs::is_directory(Path)) + return; + + if (getTriple().isKnownWindowsMSVCEnvironment()) + CmdArgs.push_back(Args.MakeArgString("-libpath:" + Path)); + else + CmdArgs.push_back(Args.MakeArgString("-L" + Path)); + }; + + // Search for flang_rt.* at the same location as clang_rt.* with + // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0. On most platforms, flang_rt is + // located at the path returned by getRuntimePath() which is already added to + // the library search path. This exception is for Apple-Darwin. + AddLibSearchPathIfExists(getCompilerRTPath()); + + // Fall back to the non-resource directory /../lib. We will + // probably have to refine this in the future. In particular, on some + // platforms, we may need to use lib64 instead of lib. SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(getDriver().Dir); llvm::sys::path::append(DefaultLibPath, "lib"); - if (getTriple().isKnownWindowsMSVCEnvironment()) - CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath)); - else - CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); + AddLibSearchPathIfExists(DefaultLibPath); } void ToolChain::addFlangRTLibPath(const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index 6bd710ec6b8b5..418f9fd9ca4c4 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -467,3 +467,18 @@ void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args, break; } } + +/// Is the triple {aarch64.aarch64_be}-none-elf? +bool aarch64::isAArch64BareMetal(const llvm::Triple &Triple) { + if (Triple.getArch() != llvm::Triple::aarch64 && + Triple.getArch() != llvm::Triple::aarch64_be) + return false; + + if (Triple.getVendor() != llvm::Triple::UnknownVendor) + return false; + + if (Triple.getOS() != llvm::Triple::UnknownOS) + return false; + + return Triple.getEnvironmentName() == "elf"; +} diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.h b/clang/lib/Driver/ToolChains/Arch/AArch64.h index 2057272867a17..2765ee8c3a6aa 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.h +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.h @@ -30,6 +30,7 @@ std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args, void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args, llvm::Triple &triple); +bool isAArch64BareMetal(const llvm::Triple &Triple); } // end namespace aarch64 } // end namespace target diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp index 9595ee8383c85..94a94f1e9c487 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp @@ -23,7 +23,9 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name, if (Triple.getArch() == llvm::Triple::sparcv9) { const char *DefV9CPU; - if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) + if (Triple.isOSSolaris()) + DefV9CPU = "-Av9b"; + else if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) DefV9CPU = "-Av9a"; else DefV9CPU = "-Av9"; @@ -35,6 +37,13 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name, .Case("niagara4", "-Av9d") .Default(DefV9CPU); } else { + const char *DefV8CPU; + + if (Triple.isOSSolaris()) + DefV8CPU = "-Av8plus"; + else + DefV8CPU = "-Av8"; + return llvm::StringSwitch(Name) .Case("v8", "-Av8") .Case("supersparc", "-Av8") @@ -70,7 +79,7 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name, .Case("gr712rc", "-Aleon") .Case("leon4", "-Aleon") .Case("gr740", "-Aleon") - .Default("-Av8"); + .Default(DefV8CPU); } } @@ -130,7 +139,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, return ""; } -void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, +void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, std::vector &Features) { sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); if (FloatABI == sparc::FloatABI::Soft) @@ -150,11 +160,22 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, Features.push_back("-popc"); } + // Those OSes default to enabling VIS on 64-bit SPARC. + // See also the corresponding code for external assemblers in + // sparc::getSparcAsmModeForCPU(). + bool IsSparcV9ATarget = + (Triple.getArch() == llvm::Triple::sparcv9) && + (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()); + bool IsSparcV9BTarget = Triple.isOSSolaris(); + bool IsSparcV8PlusTarget = + Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris(); if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) { if (A->getOption().matches(options::OPT_mvis)) Features.push_back("+vis"); else Features.push_back("-vis"); + } else if (IsSparcV9ATarget) { + Features.push_back("+vis"); } if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) { @@ -162,6 +183,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, Features.push_back("+vis2"); else Features.push_back("-vis2"); + } else if (IsSparcV9BTarget) { + Features.push_back("+vis2"); } if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) { @@ -182,6 +205,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) { if (A->getOption().matches(options::OPT_mv8plus)) Features.push_back("+v8plus"); + } else if (IsSparcV8PlusTarget) { + Features.push_back("+v8plus"); } if (Args.hasArg(options::OPT_ffixed_g1)) diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h index 2b178d9df1ee3..fa25b4992cc8b 100644 --- a/clang/lib/Driver/ToolChains/Arch/Sparc.h +++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h @@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); -void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, +void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, std::vector &Features); const char *getSparcAsmModeForCPU(llvm::StringRef Name, const llvm::Triple &Triple); diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index e670696cd59ae..207150ea6f322 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/CommonArgs.h" #include "clang/Driver/InputInfo.h" +#include "Arch/AArch64.h" #include "Arch/ARM.h" #include "Arch/RISCV.h" #include "clang/Driver/Compilation.h" @@ -31,21 +32,6 @@ using namespace clang::driver; using namespace clang::driver::tools; using namespace clang::driver::toolchains; -/// Is the triple {aarch64.aarch64_be}-none-elf? -static bool isAArch64BareMetal(const llvm::Triple &Triple) { - if (Triple.getArch() != llvm::Triple::aarch64 && - Triple.getArch() != llvm::Triple::aarch64_be) - return false; - - if (Triple.getVendor() != llvm::Triple::UnknownVendor) - return false; - - if (Triple.getOS() != llvm::Triple::UnknownOS) - return false; - - return Triple.getEnvironmentName() == "elf"; -} - static bool isRISCVBareMetal(const llvm::Triple &Triple) { if (!Triple.isRISCV()) return false; @@ -363,8 +349,9 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple, } bool BareMetal::handlesTarget(const llvm::Triple &Triple) { - return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) || - isRISCVBareMetal(Triple) || isPPCBareMetal(Triple); + return arm::isARMEABIBareMetal(Triple) || + aarch64::isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) || + isPPCBareMetal(Triple); } Tool *BareMetal::buildLinker() const { @@ -694,9 +681,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, NeedCRTs) CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd))); - if (TC.getTriple().isRISCV()) - CmdArgs.push_back("-X"); - // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and // arm*-*-*bsd). diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 456bfe885f354..62613322320cd 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, options::OPT_fno_ptrauth_objc_interface_sel); Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro, options::OPT_fno_ptrauth_objc_class_ro); - if (Triple.getEnvironment() == llvm::Triple::PAuthTest) handlePAuthABI(Args, CmdArgs); @@ -2731,16 +2730,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back(MipsTargetFeature); } - // Those OSes default to enabling VIS on 64-bit SPARC. - // See also the corresponding code for external assemblers in - // sparc::getSparcAsmModeForCPU(). - bool IsSparcV9ATarget = - (C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) && - (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()); - if (IsSparcV9ATarget && SparcTargetFeatures.empty()) { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vis"); - } for (const char *Feature : SparcTargetFeatures) { CmdArgs.push_back("-target-feature"); CmdArgs.push_back(Feature); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 097d186ad8ea4..8d3775de9be5e 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -547,15 +547,22 @@ const char *tools::getLDMOption(const llvm::Triple &T, const ArgList &Args) { case llvm::Triple::aarch64: if (T.isOSManagarm()) return "aarch64managarm"; + else if (aarch64::isAArch64BareMetal(T)) + return "aarch64elf"; return "aarch64linux"; case llvm::Triple::aarch64_be: + if (aarch64::isAArch64BareMetal(T)) + return "aarch64elfb"; return "aarch64linuxb"; case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::armeb: - case llvm::Triple::thumbeb: - return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi" - : "armelf_linux_eabi"; + case llvm::Triple::thumbeb: { + bool IsBigEndian = tools::arm::isARMBigEndian(T, Args); + if (arm::isARMEABIBareMetal(T)) + return IsBigEndian ? "armelfb" : "armelf"; + return IsBigEndian ? "armelfb_linux_eabi" : "armelf_linux_eabi"; + } case llvm::Triple::m68k: return "m68kelf"; case llvm::Triple::ppc: @@ -856,7 +863,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple, case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); + sparc::getSparcTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::r600: case llvm::Triple::amdgcn: @@ -1320,6 +1327,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, if (Args.hasArg(options::OPT_ftime_report)) CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes")); + + if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) { + CmdArgs.push_back( + Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue()))); + CmdArgs.push_back( + Args.MakeArgString("--thinlto-remote-compiler=" + + Twine(ToolChain.getDriver().getClangProgramPath()))); + + for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ)) + CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A)); + } } void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, @@ -3247,14 +3265,8 @@ void tools::handleVectorizeSLPArgs(const ArgList &Args, void tools::handleInterchangeLoopsArgs(const ArgList &Args, ArgStringList &CmdArgs) { - // FIXME: instead of relying on shouldEnableVectorizerAtOLevel, we may want to - // implement a separate function to infer loop interchange from opt level. - // For now, enable loop-interchange at the same opt levels as loop-vectorize. - bool EnableInterchange = shouldEnableVectorizerAtOLevel(Args, false); - OptSpecifier InterchangeAliasOption = - EnableInterchange ? options::OPT_O_Group : options::OPT_floop_interchange; - if (Args.hasFlag(options::OPT_floop_interchange, InterchangeAliasOption, - options::OPT_fno_loop_interchange, EnableInterchange)) + if (Args.hasFlag(options::OPT_floop_interchange, + options::OPT_fno_loop_interchange, false)) CmdArgs.push_back("-floop-interchange"); } diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index e5075cbcaf660..234683f2f4882 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -3187,28 +3187,46 @@ void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind); - // On arm64e, enable pointer authentication (for the return address and - // indirect calls), as well as usage of the intrinsics. - if (getArchName() == "arm64e") { + // On arm64e, we enable all the features required for the Darwin userspace + // ABI + if (getTriple().isArm64e()) { + // Core platform ABI + if (!DriverArgs.hasArg(options::OPT_fptrauth_calls, + options::OPT_fno_ptrauth_calls)) + CC1Args.push_back("-fptrauth-calls"); if (!DriverArgs.hasArg(options::OPT_fptrauth_returns, options::OPT_fno_ptrauth_returns)) CC1Args.push_back("-fptrauth-returns"); - if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics, options::OPT_fno_ptrauth_intrinsics)) CC1Args.push_back("-fptrauth-intrinsics"); - - if (!DriverArgs.hasArg(options::OPT_fptrauth_calls, - options::OPT_fno_ptrauth_calls)) - CC1Args.push_back("-fptrauth-calls"); - if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos, options::OPT_fno_ptrauth_indirect_gotos)) CC1Args.push_back("-fptrauth-indirect-gotos"); - if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps, options::OPT_fno_ptrauth_auth_traps)) CC1Args.push_back("-fptrauth-auth-traps"); + + // C++ v-table ABI + if (!DriverArgs.hasArg( + options::OPT_fptrauth_vtable_pointer_address_discrimination, + options::OPT_fno_ptrauth_vtable_pointer_address_discrimination)) + CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination"); + if (!DriverArgs.hasArg( + options::OPT_fptrauth_vtable_pointer_type_discrimination, + options::OPT_fno_ptrauth_vtable_pointer_type_discrimination)) + CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination"); + + // Objective-C ABI + if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_isa, + options::OPT_fno_ptrauth_objc_isa)) + CC1Args.push_back("-fptrauth-objc-isa"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_class_ro, + options::OPT_fno_ptrauth_objc_class_ro)) + CC1Args.push_back("-fptrauth-objc-class-ro"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_interface_sel, + options::OPT_fno_ptrauth_objc_interface_sel)) + CC1Args.push_back("-fptrauth-objc-interface-sel"); } } diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 1edb83f7255eb..7ab41e9b85a04 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args, // Add the target features. switch (TC.getArch()) { default: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); break; case llvm::Triple::aarch64: getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index b2e36ae6f97c3..4894e6a52e93d 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmingwex"); - for (auto Lib : Args.getAllArgValues(options::OPT_l)) + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { if (StringRef(Lib).starts_with("msvcr") || StringRef(Lib).starts_with("ucrt") || - StringRef(Lib).starts_with("crtdll")) + StringRef(Lib).starts_with("crtdll")) { + std::string CRTLib = (llvm::Twine("-l") + Lib).str(); + // Respect the user's chosen crt variant, but still provide it + // again as the last linker argument, because some of the libraries + // we added above may depend on it. + CmdArgs.push_back(Args.MakeArgStringRef(CRTLib)); return; + } + } CmdArgs.push_back("-lmsvcrt"); } diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 79b1b6960da1f..8f589186af343 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Nopie || Profiling) CmdArgs.push_back("-nopie"); - if (Triple.isRISCV64()) { + if (Triple.isLoongArch64() || Triple.isRISCV64()) { CmdArgs.push_back("-X"); if (Args.hasArg(options::OPT_mno_relax)) CmdArgs.push_back("--no-relax"); diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 791afc1a97575..00138c14ddcc2 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -636,7 +636,10 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { DeclarationFragments::FragmentKind::InternalParam); } else { Fragments.append(std::move(TypeFragments)); - if (!T->isAnyPointerType() && !T->isBlockPointerType()) + // If the type is a type alias, append the space + // even if the underlying type is a pointer type. + if (T->isTypedefNameType() || + (!T->isAnyPointerType() && !T->isBlockPointerType())) Fragments.appendSpace(); Fragments .append(Param->getName(), diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 4010f7fbd25be..38104f6c78a62 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -411,7 +411,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { } if (CurrentState.BreakBeforeClosingBrace && (Current.closesBlockOrBlockTypeList(Style) || - (Current.is(tok::r_brace) && + (Current.is(tok::r_brace) && Current.MatchingParen && Current.isBlockIndentedInitRBrace(Style)))) { return true; } @@ -628,9 +628,16 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { // name. !Style.isJavaScript() && Previous.isNot(tok::kw_template) && CurrentState.BreakBeforeParameter) { - for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) - if (Tok->FirstAfterPPLine || Tok->is(TT_LineComment)) + for (const auto *Tok = &Previous; Tok; Tok = Tok->Previous) { + if (Tok->is(TT_LineComment)) + return false; + if (Tok->is(TT_TemplateCloser)) { + Tok = Tok->MatchingParen; + assert(Tok); + } + if (Tok->FirstAfterPPLine) return false; + } return true; } diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 78c09be458f0a..5bdb810a3925b 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -727,6 +727,7 @@ template <> struct MappingTraits { IO.mapOptional("AfterFunctionDeclarationName", Spacing.AfterFunctionDeclarationName); IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); + IO.mapOptional("AfterNot", Spacing.AfterNot); IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator); IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause); @@ -1748,7 +1749,6 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.AttributeMacros.push_back("absl_nullable"); GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown"); GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; - GoogleStyle.DerivePointerAlignment = true; GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; GoogleStyle.IncludeStyle.IncludeCategories = {{"^", 2, 0, false}, {"^<.*\\.h>", 1, 0, false}, @@ -1857,6 +1857,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { } else if (Language == FormatStyle::LK_ObjC) { GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.ColumnLimit = 100; + GoogleStyle.DerivePointerAlignment = true; // "Regroup" doesn't work well for ObjC yet (main header heuristic, // relationship between ObjC standard library headers and other heades, // #imports, etc.) @@ -2131,48 +2132,70 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config, Input >> Styles; if (Input.error()) return Input.error(); + if (Styles.empty()) + return make_error_code(ParseError::Success); + + const auto StyleCount = Styles.size(); - for (unsigned i = 0; i < Styles.size(); ++i) { - // Ensures that only the first configuration can skip the Language option. - if (Styles[i].Language == FormatStyle::LK_None && i != 0) + // Start from the second style as (only) the first one may be the default. + for (unsigned I = 1; I < StyleCount; ++I) { + const auto Lang = Styles[I].Language; + if (Lang == FormatStyle::LK_None) return make_error_code(ParseError::Error); // Ensure that each language is configured at most once. - for (unsigned j = 0; j < i; ++j) { - if (Styles[i].Language == Styles[j].Language) { + for (unsigned J = 0; J < I; ++J) { + if (Lang == Styles[J].Language) { LLVM_DEBUG(llvm::dbgs() << "Duplicate languages in the config file on positions " - << j << " and " << i << "\n"); + << J << " and " << I << '\n'); return make_error_code(ParseError::Error); } } } - // Look for a suitable configuration starting from the end, so we can - // find the configuration for the specific language first, and the default - // configuration (which can only be at slot 0) after it. - FormatStyle::FormatStyleSet StyleSet; - bool LanguageFound = false; - for (const FormatStyle &Style : llvm::reverse(Styles)) { - const auto Lang = Style.Language; - if (Lang != FormatStyle::LK_None) - StyleSet.Add(Style); - if (Lang == Language || - // For backward compatibility. - (Lang == FormatStyle::LK_Cpp && Language == FormatStyle::LK_C)) { - LanguageFound = true; - } else if (IsDotHFile && Language == FormatStyle::LK_Cpp && - (Lang == FormatStyle::LK_C || Lang == FormatStyle::LK_ObjC)) { - Language = Lang; - LanguageFound = true; + + int LanguagePos = -1; // Position of the style for Language. + int CppPos = -1; // Position of the style for C++. + int CPos = -1; // Position of the style for C. + + // Search Styles for Language and store the positions of C++ and C styles in + // case Language is not found. + for (unsigned I = 0; I < StyleCount; ++I) { + const auto Lang = Styles[I].Language; + if (Lang == Language) { + LanguagePos = I; + break; } - } - if (!LanguageFound) { - if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) + if (Lang == FormatStyle::LK_Cpp) + CppPos = I; + else if (Lang == FormatStyle::LK_C) + CPos = I; + } + + // If Language is not found, use the default style if there is one. Otherwise, + // use the C style for C++ .h files and for backward compatibility, the C++ + // style for .c files. + if (LanguagePos < 0) { + if (Styles[0].Language == FormatStyle::LK_None) // Default style. + LanguagePos = 0; + else if (IsDotHFile && Language == FormatStyle::LK_Cpp) + LanguagePos = CPos; + else if (!IsDotHFile && Language == FormatStyle::LK_C) + LanguagePos = CppPos; + if (LanguagePos < 0) return make_error_code(ParseError::Unsuitable); - FormatStyle DefaultStyle = Styles[0]; - DefaultStyle.Language = Language; - StyleSet.Add(std::move(DefaultStyle)); } - *Style = *StyleSet.Get(Language); + + for (const auto &S : llvm::reverse(llvm::drop_begin(Styles))) + Style->StyleSet.Add(S); + + *Style = Styles[LanguagePos]; + + if (LanguagePos == 0) { + if (Style->Language == FormatStyle::LK_None) // Default style. + Style->Language = Language; + Style->StyleSet.Add(*Style); + } + if (Style->InsertTrailingCommas != FormatStyle::TCS_None && Style->BinPackArguments) { // See comment on FormatStyle::TSC_Wrapped. @@ -2203,14 +2226,8 @@ FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { if (!Styles) return std::nullopt; auto It = Styles->find(Language); - if (It == Styles->end()) { - if (Language != FormatStyle::LK_C) - return std::nullopt; - // For backward compatibility. - It = Styles->find(FormatStyle::LK_Cpp); - if (It == Styles->end()) - return std::nullopt; - } + if (It == Styles->end()) + return std::nullopt; FormatStyle Style = It->second; Style.StyleSet = *this; return Style; @@ -4042,6 +4059,7 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) { switch (Style.Language) { case FormatStyle::LK_C: LangOpts.C11 = 1; + LangOpts.C23 = 1; break; case FormatStyle::LK_Cpp: case FormatStyle::LK_ObjC: diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index 0d8ae1c4a77eb..a32175ecc02bc 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -53,12 +53,13 @@ bool FormatToken::isTypeOrIdentifier(const LangOptions &LangOpts) const { bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const { assert(is(tok::r_brace)); + assert(MatchingParen); + assert(MatchingParen->is(tok::l_brace)); if (!Style.Cpp11BracedListStyle || Style.AlignAfterOpenBracket != FormatStyle::BAS_BlockIndent) { return false; } const auto *LBrace = MatchingParen; - assert(LBrace && LBrace->is(tok::l_brace)); if (LBrace->is(BK_BracedInit)) return true; if (LBrace->Previous && LBrace->Previous->is(tok::equal)) diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 9252a795a0b5e..c2000a971c898 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -55,7 +55,7 @@ namespace format { TYPE(ConflictAlternative) \ TYPE(ConflictEnd) \ TYPE(ConflictStart) \ - /* l_brace of if/for/while */ \ + /* l_brace of if/for/while/switch/catch */ \ TYPE(ControlStatementLBrace) \ TYPE(ControlStatementRBrace) \ TYPE(CppCastLParen) \ diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp index 49da3160daf50..165ede2d04b2c 100644 --- a/clang/lib/Format/FormatTokenLexer.cpp +++ b/clang/lib/Format/FormatTokenLexer.cpp @@ -93,12 +93,6 @@ ArrayRef FormatTokenLexer::lex() { auto &Tok = *Tokens.back(); const auto NewlinesBefore = Tok.NewlinesBefore; switch (FormatOff) { - case FO_CurrentLine: - if (NewlinesBefore == 0) - Tok.Finalized = true; - else - FormatOff = FO_None; - break; case FO_NextLine: if (NewlinesBefore > 1) { FormatOff = FO_None; @@ -107,6 +101,13 @@ ArrayRef FormatTokenLexer::lex() { FormatOff = FO_CurrentLine; } break; + case FO_CurrentLine: + if (NewlinesBefore == 0) { + Tok.Finalized = true; + break; + } + FormatOff = FO_None; + [[fallthrough]]; default: if (!FormattingDisabled && FormatOffRegex.match(Tok.TokenText)) { if (Tok.is(tok::comment) && diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index 87823ae32b113..aa752f5e3148a 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -45,15 +45,18 @@ std::pair IntegerLiteralSeparatorFixer::process(const Environment &Env, const FormatStyle &Style) { switch (Style.Language) { - case FormatStyle::LK_Cpp: - case FormatStyle::LK_ObjC: - Separator = '\''; - break; case FormatStyle::LK_CSharp: case FormatStyle::LK_Java: case FormatStyle::LK_JavaScript: Separator = '_'; break; + case FormatStyle::LK_Cpp: + case FormatStyle::LK_ObjC: + if (Style.Standard >= FormatStyle::LS_Cpp14) { + Separator = '\''; + break; + } + [[fallthrough]]; default: return {}; } diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp index 441a37a4902b7..cc59dbd13621d 100644 --- a/clang/lib/Format/QualifierAlignmentFixer.cpp +++ b/clang/lib/Format/QualifierAlignmentFixer.cpp @@ -182,8 +182,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( // We only need to think about streams that begin with a qualifier. if (Tok->isNot(QualifierType)) return Tok; + + const auto *Next = Tok->getNextNonComment(); + // Don't concern yourself if nothing follows the qualifier. - if (!Tok->Next) + if (!Next) return Tok; // Skip qualifiers to the left to find what preceeds the qualifiers. @@ -247,9 +250,15 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight( }(); // Find the last qualifier to the right. - const FormatToken *LastQual = Tok; - while (isQualifier(LastQual->getNextNonComment())) - LastQual = LastQual->getNextNonComment(); + const auto *LastQual = Tok; + for (; isQualifier(Next); Next = Next->getNextNonComment()) + LastQual = Next; + + if (!LastQual || !Next || + (LastQual->isOneOf(tok::kw_const, tok::kw_volatile) && + Next->isOneOf(Keywords.kw_override, Keywords.kw_final))) { + return Tok; + } // If this qualifier is to the right of a type or pointer do a partial sort // and return. diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 739209a5681f8..57b2872566a47 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -829,11 +829,6 @@ class AnnotatingParser { if (Parent && Parent->is(TT_PointerOrReference)) Parent->overwriteFixedType(TT_BinaryOperator); } - // An arrow after an ObjC method expression is not a lambda arrow. - if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next && - CurrentToken->Next->is(TT_LambdaArrow)) { - CurrentToken->Next->overwriteFixedType(TT_Unknown); - } Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; // FirstObjCSelectorName is set when a colon is found. This does @@ -2590,6 +2585,9 @@ class AnnotatingParser { if (!Tok.Previous || Tok.isNot(tok::identifier) || Tok.is(TT_ClassHeadName)) return false; + if (Tok.endsSequence(Keywords.kw_final, TT_ClassHeadName)) + return false; + if ((Style.isJavaScript() || Style.isJava()) && Tok.is(Keywords.kw_extends)) return false; @@ -2996,14 +2994,18 @@ class AnnotatingParser { const FormatToken *PrevToken = Tok.getPreviousNonComment(); if (!PrevToken) return TT_UnaryOperator; - if (PrevToken->is(TT_TypeName)) + if (PrevToken->isTypeName(LangOpts)) return TT_PointerOrReference; if (PrevToken->isPlacementOperator() && Tok.is(tok::ampamp)) return TT_BinaryOperator; - const FormatToken *NextToken = Tok.getNextNonComment(); + auto *NextToken = Tok.getNextNonComment(); if (!NextToken) return TT_PointerOrReference; + if (NextToken->is(tok::greater)) { + NextToken->setFinalizedType(TT_TemplateCloser); + return TT_PointerOrReference; + } if (InTemplateArgument && NextToken->is(tok::kw_noexcept)) return TT_BinaryOperator; @@ -3112,7 +3114,7 @@ class AnnotatingParser { // It's more likely that & represents operator& than an uninitialized // reference. - if (Tok.is(tok::amp) && PrevToken && PrevToken->Tok.isAnyIdentifier() && + if (Tok.is(tok::amp) && PrevToken->Tok.isAnyIdentifier() && IsChainedOperatorAmpOrMember(PrevToken->getPreviousNonComment()) && NextToken && NextToken->Tok.isAnyIdentifier()) { if (auto NextNext = NextToken->getNextNonComment(); @@ -3773,18 +3775,12 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, if (Current.is(TT_FunctionDeclarationName)) return true; - if (!Current.Tok.getIdentifierInfo()) + if (!Current.isOneOf(tok::identifier, tok::kw_operator)) return false; const auto *Prev = Current.getPreviousNonComment(); assert(Prev); - if (Prev->is(tok::coloncolon)) - Prev = Prev->Previous; - - if (!Prev) - return false; - const auto &Previous = *Prev; if (const auto *PrevPrev = Previous.getPreviousNonComment(); @@ -3833,6 +3829,8 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts, // Find parentheses of parameter list. if (Current.is(tok::kw_operator)) { + if (Line.startsWith(tok::kw_friend)) + return true; if (Previous.Tok.getIdentifierInfo() && !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { return true; @@ -3998,29 +3996,28 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } - if (IsCpp && - (LineIsFunctionDeclaration || - (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) && - Line.endsWith(tok::semi, tok::r_brace)) { - auto *Tok = Line.Last->Previous; - while (Tok->isNot(tok::r_brace)) - Tok = Tok->Previous; - if (auto *LBrace = Tok->MatchingParen; LBrace) { - assert(LBrace->is(tok::l_brace)); - Tok->setBlockKind(BK_Block); - LBrace->setBlockKind(BK_Block); - LBrace->setFinalizedType(TT_FunctionLBrace); + if (IsCpp) { + if ((LineIsFunctionDeclaration || + (FirstNonComment && FirstNonComment->is(TT_CtorDtorDeclName))) && + Line.endsWith(tok::semi, tok::r_brace)) { + auto *Tok = Line.Last->Previous; + while (Tok->isNot(tok::r_brace)) + Tok = Tok->Previous; + if (auto *LBrace = Tok->MatchingParen; LBrace && LBrace->is(TT_Unknown)) { + assert(LBrace->is(tok::l_brace)); + Tok->setBlockKind(BK_Block); + LBrace->setBlockKind(BK_Block); + LBrace->setFinalizedType(TT_FunctionLBrace); + } } - } - if (IsCpp && SeenName && AfterLastAttribute && - mustBreakAfterAttributes(*AfterLastAttribute, Style)) { - AfterLastAttribute->MustBreakBefore = true; - if (LineIsFunctionDeclaration) - Line.ReturnTypeWrapped = true; - } + if (SeenName && AfterLastAttribute && + mustBreakAfterAttributes(*AfterLastAttribute, Style)) { + AfterLastAttribute->MustBreakBefore = true; + if (LineIsFunctionDeclaration) + Line.ReturnTypeWrapped = true; + } - if (IsCpp) { if (!LineIsFunctionDeclaration) { // Annotate */&/&& in `operator` function calls as binary operators. for (const auto *Tok = FirstNonComment; Tok; Tok = Tok->Next) { @@ -4066,6 +4063,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const { } } + if (First->is(TT_ElseLBrace)) { + First->CanBreakBefore = true; + First->MustBreakBefore = true; + } + bool InFunctionDecl = Line.MightBeFunctionDecl; bool InParameterList = false; for (auto *Current = First->Next; Current; Current = Current->Next) { @@ -5474,7 +5476,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Left.TokenText == "!") return Style.SpaceAfterLogicalNot; assert(Left.TokenText == "not"); - return Right.isOneOf(tok::coloncolon, TT_UnaryOperator); + return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) || + (Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot); } // If the next token is a binary operator or a selector name, we have @@ -6266,7 +6269,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, } if (Right.is(tok::colon) && - !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon)) { + !Right.isOneOf(TT_CtorInitializerColon, TT_InlineASMColon, + TT_BitFieldColon)) { return false; } if (Left.is(tok::colon) && Left.isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)) { diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 91b8fdc8a3c38..3df071a197c67 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2266,7 +2266,7 @@ bool UnwrappedLineParser::tryToParseLambda() { if (!tryToParseLambdaIntroducer()) return false; - bool SeenArrow = false; + FormatToken *Arrow = nullptr; bool InTemplateParameterList = false; while (FormatTok->isNot(tok::l_brace)) { @@ -2341,17 +2341,13 @@ bool UnwrappedLineParser::tryToParseLambda() { case tok::ellipsis: case tok::kw_true: case tok::kw_false: - if (SeenArrow || InTemplateParameterList) { + if (Arrow || InTemplateParameterList) { nextToken(); break; } return true; case tok::arrow: - // This might or might not actually be a lambda arrow (this could be an - // ObjC method invocation followed by a dereferencing arrow). We might - // reset this back to TT_Unknown in TokenAnnotator. - FormatTok->setFinalizedType(TT_LambdaArrow); - SeenArrow = true; + Arrow = FormatTok; nextToken(); break; case tok::kw_requires: { @@ -2373,6 +2369,9 @@ bool UnwrappedLineParser::tryToParseLambda() { FormatTok->setFinalizedType(TT_LambdaLBrace); LSquare.setFinalizedType(TT_LambdaLSquare); + if (Arrow) + Arrow->setFinalizedType(TT_LambdaArrow); + NestedLambdas.push_back(Line->SeenDecltypeAuto); parseChildBlock(); assert(!NestedLambdas.empty()); @@ -2386,21 +2385,23 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() { const FormatToken *LeftSquare = FormatTok; nextToken(); if (Previous) { - if (Previous->Tok.getIdentifierInfo() && - !Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield, - tok::kw_co_return)) { + const auto *PrevPrev = Previous->getPreviousNonComment(); + if (Previous->is(tok::star) && PrevPrev && PrevPrev->isTypeName(LangOpts)) return false; - } if (Previous->closesScope()) { // Not a potential C-style cast. if (Previous->isNot(tok::r_paren)) return false; - const auto *BeforeRParen = Previous->getPreviousNonComment(); // Lambdas can be cast to function types only, e.g. `std::function` // and `int (*)()`. - if (!BeforeRParen || !BeforeRParen->isOneOf(tok::greater, tok::r_paren)) + if (!PrevPrev || !PrevPrev->isOneOf(tok::greater, tok::r_paren)) return false; } + if (Previous && Previous->Tok.getIdentifierInfo() && + !Previous->isOneOf(tok::kw_return, tok::kw_co_await, tok::kw_co_yield, + tok::kw_co_return)) { + return false; + } } if (LeftSquare->isCppStructuredBinding(IsCpp)) return false; diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index cc3cc0f6906cc..ecc696c539226 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1295,7 +1295,10 @@ void WhitespaceManager::alignArrayInitializers() { bool FoundComplete = false; for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd; ++InsideIndex) { - if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) { + const auto *Tok = Changes[InsideIndex].Tok; + if (Tok->is(tok::pp_define)) + break; + if (Tok == C.Tok->MatchingParen) { alignArrayInitializers(ChangeIndex, InsideIndex + 1); ChangeIndex = InsideIndex + 1; FoundComplete = true; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 08cf0ae6b2c24..08f3b7a7fcc49 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions( Discrimination::Constant, InitFiniPointerConstantDiscriminator); } + Opts.BlockInvocationFunctionPointers = + PointerAuthSchema(Key::ASIA, true, Discrimination::None); + Opts.BlockHelperFunctionPointers = + PointerAuthSchema(Key::ASIA, true, Discrimination::None); + Opts.BlockByrefHelperFunctionPointers = + PointerAuthSchema(Key::ASIA, true, Discrimination::None); + if (LangOpts.PointerAuthBlockDescriptorPointers) + Opts.BlockDescriptorPointers = + PointerAuthSchema(Key::ASDA, true, Discrimination::Constant, + BlockDescriptorConstantDiscriminator); + Opts.ObjCMethodListFunctionPointers = PointerAuthSchema(Key::ASIA, true, Discrimination::None); Opts.ObjCMethodListPointer = @@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel); if (Opts.PointerAuthObjcClassROPointers) GenerateArg(Consumer, OPT_fptrauth_objc_class_ro); + if (Opts.PointerAuthBlockDescriptorPointers) + GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers); } static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, @@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); Opts.AArch64JumpTableHardening = Args.hasArg(OPT_faarch64_jump_table_hardening); - + Opts.PointerAuthBlockDescriptorPointers = + Args.hasArg(OPT_fptrauth_block_descriptor_pointers); Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa); Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro); Opts.PointerAuthObjcInterfaceSel = diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 34fb825e9d420..cce8392950b03 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1535,6 +1535,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, #undef TARGET_OS } + if (LangOpts.PointerAuthIntrinsics) + Builder.defineMacro("__PTRAUTH__"); + // Get other target #defines. TI.getTargetDefines(LangOpts, Builder); } diff --git a/clang/lib/Headers/avx10_2_512niintrin.h b/clang/lib/Headers/avx10_2_512niintrin.h index 7e614f7740bff..9d96e36c74ca4 100644 --- a/clang/lib/Headers/avx10_2_512niintrin.h +++ b/clang/lib/Headers/avx10_2_512niintrin.h @@ -197,7 +197,7 @@ _mm512_mask_dpwsud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsud_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwsud_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); @@ -218,7 +218,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwsuds_epi32( } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwsuds_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwsuds_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); @@ -239,7 +239,7 @@ _mm512_mask_dpwusd_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusd_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwusd_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); @@ -260,7 +260,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwusds_epi32( } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwusds_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwusds_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); @@ -281,7 +281,7 @@ _mm512_mask_dpwuud_epi32(__m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuud_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwuud_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); @@ -302,7 +302,7 @@ static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_mask_dpwuuds_epi32( } static __inline__ __m512i __DEFAULT_FN_ATTRS _mm512_maskz_dpwuuds_epi32( - __m512i __A, __mmask16 __U, __m512i __B, __m512i __C) { + __mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { return (__m512i)__builtin_ia32_selectd_512( (__mmask16)__U, (__v16si)_mm512_dpwuuds_epi32(__A, __B, __C), (__v16si)_mm512_setzero_si512()); diff --git a/clang/lib/Headers/avx10_2bf16intrin.h b/clang/lib/Headers/avx10_2bf16intrin.h index 66797ae00fe4f..0ca5380829391 100644 --- a/clang/lib/Headers/avx10_2bf16intrin.h +++ b/clang/lib/Headers/avx10_2bf16intrin.h @@ -519,34 +519,34 @@ _mm_maskz_min_pbh(__mmask8 __U, __m128bh __A, __m128bh __B) { (__mmask8)__U, (__v8bf)_mm_min_pbh(__A, __B), (__v8bf)_mm_setzero_pbh()); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16eq((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comieq_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16eq((__v8bf)__A, (__v8bf)__B); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16lt((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comilt_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16lt((__v8bf)__A, (__v8bf)__B); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16le((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comile_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16le((__v8bf)__A, (__v8bf)__B); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16gt((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comigt_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16gt((__v8bf)__A, (__v8bf)__B); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16ge((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comige_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16ge((__v8bf)__A, (__v8bf)__B); } -static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh A, - __m128bh B) { - return __builtin_ia32_vcomisbf16neq((__v8bf)A, (__v8bf)B); +static __inline__ int __DEFAULT_FN_ATTRS128 _mm_comineq_sbh(__m128bh __A, + __m128bh __B) { + return __builtin_ia32_vcomisbf16neq((__v8bf)__A, (__v8bf)__B); } #define _mm256_cmp_pbh_mask(__A, __B, __P) \ diff --git a/clang/lib/Headers/avx10_2niintrin.h b/clang/lib/Headers/avx10_2niintrin.h index 992be18f7720a..d5a66cfef536c 100644 --- a/clang/lib/Headers/avx10_2niintrin.h +++ b/clang/lib/Headers/avx10_2niintrin.h @@ -253,7 +253,7 @@ _mm_mask_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwsud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwsud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwsud_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -266,7 +266,7 @@ _mm256_mask_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_maskz_dpwsud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { +_mm256_maskz_dpwsud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwsud_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); @@ -279,7 +279,7 @@ _mm_mask_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwsuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwsuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwsuds_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -292,7 +292,7 @@ _mm256_mask_dpwsuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwsuds_epi32( - __m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { + __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwsuds_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); @@ -305,7 +305,7 @@ _mm_mask_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwusd_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwusd_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwusd_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -318,7 +318,7 @@ _mm256_mask_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_maskz_dpwusd_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { +_mm256_maskz_dpwusd_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwusd_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); @@ -331,7 +331,7 @@ _mm_mask_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwusds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwusds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwusds_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -344,7 +344,7 @@ _mm256_mask_dpwusds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwusds_epi32( - __m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { + __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwusds_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); @@ -357,7 +357,7 @@ _mm_mask_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwuud_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwuud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwuud_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -370,7 +370,7 @@ _mm256_mask_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 -_mm256_maskz_dpwuud_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { +_mm256_maskz_dpwuud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwuud_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); @@ -383,7 +383,7 @@ _mm_mask_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { } static __inline__ __m128i __DEFAULT_FN_ATTRS128 -_mm_maskz_dpwuuds_epi32(__m128i __A, __mmask8 __U, __m128i __B, __m128i __C) { +_mm_maskz_dpwuuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { return (__m128i)__builtin_ia32_selectd_128( (__mmask8)__U, (__v4si)_mm_dpwuuds_epi32(__A, __B, __C), (__v4si)_mm_setzero_si128()); @@ -396,7 +396,7 @@ _mm256_mask_dpwuuds_epi32(__m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { } static __inline__ __m256i __DEFAULT_FN_ATTRS256 _mm256_maskz_dpwuuds_epi32( - __m256i __A, __mmask8 __U, __m256i __B, __m256i __C) { + __mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { return (__m256i)__builtin_ia32_selectd_256( (__mmask8)__U, (__v8si)_mm256_dpwuuds_epi32(__A, __B, __C), (__v8si)_mm256_setzero_si256()); diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index 2b7f5043e09e4..6206a347852be 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -697,7 +697,16 @@ template struct __remove_address_space<__constant _Tp> { #if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) // OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf -int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))); +#ifdef __OPENCL_CPP_VERSION__ +#define CLINKAGE extern "C" +#else +#define CLINKAGE +#endif + +CLINKAGE int printf(__constant const char *st, ...) + __attribute__((format(printf, 1, 2))); + +#undef CLINKAGE #endif #ifdef cl_intel_device_side_avc_motion_estimation diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h index 7f7d387cbdfda..f902ca1e3bbd3 100644 --- a/clang/lib/Headers/ptrauth.h +++ b/clang/lib/Headers/ptrauth.h @@ -95,7 +95,7 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; __ptrauth qualifier; the compiler will perform this check automatically. */ -#if __has_feature(ptrauth_intrinsics) +#if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) /* Strip the signature from a value without authenticating it. @@ -388,6 +388,6 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; #define __ptrauth_objc_isa_uintptr #define __ptrauth_objc_super_pointer -#endif /* __has_feature(ptrauth_intrinsics) */ +#endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */ #endif /* __PTRAUTH_H */ diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 1f695b4a8676c..b282a600c0e56 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -174,8 +174,6 @@ void Lexer::InitLexer(const char *BufStart, const char *BufPtr, ExtendedTokenMode = 0; NewLinePtr = nullptr; - - IsFirstPPToken = true; } /// Lexer constructor - Create a new lexer object for the specified buffer @@ -3225,7 +3223,6 @@ std::optional Lexer::peekNextPPToken() { bool atStartOfLine = IsAtStartOfLine; bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine; bool leadingSpace = HasLeadingSpace; - bool isFirstPPToken = IsFirstPPToken; Token Tok; Lex(Tok); @@ -3236,7 +3233,6 @@ std::optional Lexer::peekNextPPToken() { HasLeadingSpace = leadingSpace; IsAtStartOfLine = atStartOfLine; IsAtPhysicalStartOfLine = atPhysicalStartOfLine; - IsFirstPPToken = isFirstPPToken; // Restore the lexer back to non-skipping mode. LexingRawMode = false; @@ -3726,11 +3722,6 @@ bool Lexer::Lex(Token &Result) { HasLeadingEmptyMacro = false; } - if (IsFirstPPToken) { - Result.setFlag(Token::FirstPPToken); - IsFirstPPToken = false; - } - bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine; IsAtPhysicalStartOfLine = false; bool isRawLex = isLexingRawMode(); diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index a62508e3e27bf..5b08d7f0efe5a 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1467,7 +1467,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) { if (s != PossibleNewDigitStart) DigitsBegin = PossibleNewDigitStart; else - IsSingleZero = (s == ThisTokEnd); // Is the only thing we've seen a 0? + IsSingleZero = (s == ThisTokBegin + 1); if (s == ThisTokEnd) return; // Done, simple octal number like 01234 diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index bcd3ea60ce3da..2120e45dd8f8a 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -43,6 +43,7 @@ #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/NoTrivialPPDirectiveTracer.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/PreprocessorLexer.h" @@ -247,8 +248,6 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const { llvm::errs() << " [LeadingSpace]"; if (Tok.isExpandDisabled()) llvm::errs() << " [ExpandDisabled]"; - if (Tok.isFirstPPToken()) - llvm::errs() << " [First pp-token]"; if (Tok.needsCleaning()) { const char *Start = SourceMgr.getCharacterData(Tok.getLocation()); llvm::errs() << " [UnClean='" << StringRef(Start, Tok.getLength()) @@ -577,8 +576,11 @@ void Preprocessor::EnterMainSourceFile() { // export module M; // error: module declaration must occur // // at the start of the translation unit. if (getLangOpts().CPlusPlusModules) { + auto Tracer = std::make_unique(*this); + DirTracer = Tracer.get(); + addPPCallbacks(std::move(Tracer)); std::optional FirstPPTok = CurLexer->peekNextPPToken(); - if (FirstPPTok && FirstPPTok->isFirstPPToken()) + if (FirstPPTok) FirstPPTokenLoc = FirstPPTok->getLocation(); } } @@ -940,6 +942,8 @@ void Preprocessor::Lex(Token &Result) { StdCXXImportSeqState.handleHeaderName(); break; case tok::kw_export: + if (hasSeenNoTrivialPPDirective()) + Result.setFlag(Token::HasSeenNoTrivialPPDirective); TrackGMFState.handleExport(); StdCXXImportSeqState.handleExport(); ModuleDeclState.handleExport(); @@ -966,6 +970,8 @@ void Preprocessor::Lex(Token &Result) { } break; } else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) { + if (hasSeenNoTrivialPPDirective()) + Result.setFlag(Token::HasSeenNoTrivialPPDirective); TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq()); ModuleDeclState.handleModule(); break; @@ -1680,3 +1686,31 @@ const char *Preprocessor::getCheckPoint(FileID FID, const char *Start) const { return nullptr; } + +bool Preprocessor::hasSeenNoTrivialPPDirective() const { + return DirTracer && DirTracer->hasSeenNoTrivialPPDirective(); +} + +bool NoTrivialPPDirectiveTracer::hasSeenNoTrivialPPDirective() const { + return SeenNoTrivialPPDirective; +} + +void NoTrivialPPDirectiveTracer::setSeenNoTrivialPPDirective() { + if (InMainFile && !SeenNoTrivialPPDirective) + SeenNoTrivialPPDirective = true; +} + +void NoTrivialPPDirectiveTracer::LexedFileChanged( + FileID FID, LexedFileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID, SourceLocation Loc) { + InMainFile = (FID == PP.getSourceManager().getMainFileID()); +} + +void NoTrivialPPDirectiveTracer::MacroExpands(const Token &MacroNameTok, + const MacroDefinition &MD, + SourceRange Range, + const MacroArgs *Args) { + // FIXME: Does only enable builtin macro expansion make sense? + if (!MD.getMacroInfo()->isBuiltinMacro()) + setSeenNoTrivialPPDirective(); +} diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index bc238a9517a37..3515343202de1 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -3342,7 +3342,8 @@ ExprResult Parser::ParseBlockLiteralExpression() { Actions.ActOnBlockError(CaretLoc, getCurScope()); return ExprError(); } - + EnterExpressionEvaluationContextForFunction PotentiallyEvaluated( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); StmtResult Stmt(ParseCompoundStatementBody()); BlockScope.Exit(); if (!Stmt.isInvalid()) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 8834bf80c4016..447d0283431ba 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2361,9 +2361,10 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) { // Parse a global-module-fragment, if present. if (getLangOpts().CPlusPlusModules && Tok.is(tok::semi)) { SourceLocation SemiLoc = ConsumeToken(); - if (!Introducer.isFirstPPToken()) { + if (ImportState != Sema::ModuleImportState::FirstDecl || + Introducer.hasSeenNoTrivialPPDirective()) { Diag(StartLoc, diag::err_global_module_introducer_not_at_start) - << SourceRange(StartLoc, SemiLoc); + << SourceRange(StartLoc, SemiLoc); return nullptr; } if (MDK == Sema::ModuleDeclKind::Interface) { @@ -2418,7 +2419,8 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) { ExpectAndConsumeSemi(diag::err_module_expected_semi); return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path, Partition, - ImportState, Introducer.isFirstPPToken()); + ImportState, + Introducer.hasSeenNoTrivialPPDirective()); } Decl *Parser::ParseModuleImport(SourceLocation AtLoc, diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 5e75c64eb2b9a..ec39bca6039f0 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -503,8 +503,12 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk, TransferFunctions TF(VD); BackwardDataflowWorklist Worklist(*AC.getCFG(), AC); + llvm::DenseSet Visited; Worklist.enqueueBlock(&VarBlk); while (const CFGBlock *B = Worklist.dequeue()) { + if (Visited.contains(B)) + continue; + Visited.insert(B); // First check the current block. for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend(); ri != re; ++ri) { @@ -2887,8 +2891,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( .setAlwaysAdd(Stmt::UnaryOperatorClass); } - bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored( - diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc()); + bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety; // Install the logical handler. std::optional LEH; if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index dd5b710d7e1d4..41bcf8fd493fc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12014,13 +12014,20 @@ static void DiagnoseMixedUnicodeImplicitConversion(Sema &S, const Type *Source, SourceLocation CC) { assert(Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType() && Source != Target); + + // Lone surrogates have a distinct representation in UTF-32. + // Converting between UTF-16 and UTF-32 codepoints seems very widespread, + // so don't warn on such conversion. + if (Source->isChar16Type() && Target->isChar32Type()) + return; + Expr::EvalResult Result; if (E->EvaluateAsInt(Result, S.getASTContext(), Expr::SE_AllowSideEffects, S.isConstantEvaluatedContext())) { llvm::APSInt Value(32); Value = Result.Val.getInt(); bool IsASCII = Value <= 0x7F; - bool IsBMP = Value <= 0xD7FF || (Value >= 0xE000 && Value <= 0xFFFF); + bool IsBMP = Value <= 0xDFFF || (Value >= 0xE000 && Value <= 0xFFFF); bool ConversionPreservesSemantics = IsASCII || (!Source->isChar8Type() && !Target->isChar8Type() && IsBMP); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 834417f8e15ac..20567a6d9d1a8 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1097,10 +1097,6 @@ static bool CheckFunctionConstraintsWithoutInstantiation( } Sema::ContextRAII SavedContext(SemaRef, FD); - std::optional ThisScope; - if (auto *Method = dyn_cast(FD)) - ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(), - /*ThisQuals=*/Method->getMethodQualifiers()); return SemaRef.CheckConstraintSatisfaction( Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 14403e65e8f42..d43dc2297c6fb 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, if (isa(I) || isa(I)) continue; + if (isa(I)) { + if (auto *FD = dyn_cast(New)) { + if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + continue; // Don't propagate inferred noreturn attributes to explicit + // specializations. + } + } + if (mergeDeclAttribute(*this, New, I, LocalAMK)) foundAny = true; } @@ -19643,6 +19651,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Q && Q.isAddressDiscriminated()) { Record->setArgPassingRestrictions( RecordArgPassingKind::CanNeverPassInRegs); + Record->setNonTrivialToPrimitiveCopy(true); } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5f481ed1f7139..a7897bdfe6e0f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) { if (!FD) return; + // Skip explicit specializations here as they may have + // a user-provided definition that may deliberately differ from the primary + // template. If an explicit specialization truly never returns, the user + // should explicitly mark it with [[noreturn]]. + if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return; + auto *NonConstFD = const_cast(FD); DiagnosticsEngine &Diags = S.getDiagnostics(); if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) && @@ -5011,10 +5018,10 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI, static void handleNonStringAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // This only applies to fields and variable declarations which have an array - // type. + // type or pointer type, with character elements. QualType QT = cast(D)->getType(); - if (!QT->isArrayType() || - !QT->getBaseElementTypeUnsafe()->isAnyCharacterType()) { + if ((!QT->isArrayType() && !QT->isPointerType()) || + !QT->getPointeeOrArrayElementType()->isAnyCharacterType()) { S.Diag(D->getBeginLoc(), diag::warn_attribute_non_character_array) << AL << AL.isRegularKeywordAttribute() << QT << AL.getRange(); return; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 728ada33e2e63..5421e9562c8b2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9309,14 +9309,14 @@ AssignConvertType Sema::CheckAssignmentConstraints(QualType LHSType, // If we have an atomic type, try a non-atomic assignment, then just add an // atomic qualification step. if (const AtomicType *AtomicTy = dyn_cast(LHSType)) { - AssignConvertType result = + AssignConvertType Result = CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind); - if (result != AssignConvertType::Compatible) - return result; + if (!IsAssignConvertCompatible(Result)) + return Result; if (Kind != CK_NoOp && ConvertRHS) RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind); Kind = CK_NonAtomicToAtomic; - return AssignConvertType::Compatible; + return Result; } // If the left-hand side is a reference type, then we are in a diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 25afa2f4dfe7a..a08971c6526fe 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -347,6 +347,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, CheckTypenameType(ElaboratedTypeKeyword::None, SourceLocation(), SS.getWithLocInContext(Context), II, NameLoc, &TSI, /*DeducedTSTContext=*/true); + if (T.isNull()) + return ParsedType(); return CreateParsedType(T, TSI); } diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 7c982bcd63d73..10a390286ec7a 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -264,10 +264,11 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path, ModuleIdPath Partition, ModuleImportState &ImportState, - bool IntroducerIsFirstPPToken) { + bool SeenNoTrivialPPDirective) { assert(getLangOpts().CPlusPlusModules && "should only have module decl in standard C++ modules"); + bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl; bool SeenGMF = ImportState == ModuleImportState::GlobalFragment; // If any of the steps here fail, we count that as invalidating C++20 // module state; @@ -335,7 +336,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, // In C++20, A module directive may only appear as the first preprocessing // tokens in a file (excluding the global module fragment.). - if (getLangOpts().CPlusPlusModules && !IntroducerIsFirstPPToken && !SeenGMF) { + if (getLangOpts().CPlusPlusModules && + (!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) { Diag(ModuleLoc, diag::err_module_decl_not_at_start); SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc(); Diag(BeginLoc, diag::note_global_module_introducer_missing) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f3baf0c3ef3bc..1b54628c5e564 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -245,7 +245,6 @@ void StandardConversionSequence::setAsIdentityConversion() { IsLvalueReference = true; BindsToFunctionLvalue = false; BindsToRvalue = false; - IsImplicitObjectArgumentQualificationConversion = false; BindsImplicitObjectArgumentWithoutRefQualifier = false; ObjCLifetimeConversionBinding = false; FromBracedInitList = false; @@ -5318,7 +5317,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.Standard.DirectBinding = BindsDirectly; ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false; ICS.Standard.BindsToRvalue = InitCategory.isRValue(); ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.ObjCLifetimeConversionBinding = @@ -5498,7 +5496,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = false; ICS.Standard.BindsToRvalue = true; - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = false; ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.ObjCLifetimeConversionBinding = false; } else if (ICS.isUserDefined()) { @@ -5521,8 +5518,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, ICS.UserDefined.After.IsLvalueReference = !isRValRef; ICS.UserDefined.After.BindsToFunctionLvalue = false; ICS.UserDefined.After.BindsToRvalue = !LValRefType; - ICS.UserDefined.After.IsImplicitObjectArgumentQualificationConversion = - false; ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.UserDefined.After.ObjCLifetimeConversionBinding = false; ICS.UserDefined.After.FromBracedInitList = false; @@ -5807,7 +5802,6 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard : Result.UserDefined.After; SCS.ReferenceBinding = true; - SCS.IsImplicitObjectArgumentQualificationConversion = false; SCS.IsLvalueReference = ToType->isLValueReferenceType(); SCS.BindsToRvalue = true; SCS.BindsToFunctionLvalue = false; @@ -6005,12 +5999,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( // affects the conversion rank. QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); ImplicitConversionKind SecondKind; - bool IsQualificationConversion = false; - if (ImplicitParamType.getCanonicalType() == FromTypeCanon) { + if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { SecondKind = ICK_Identity; - } else if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { - SecondKind = ICK_Identity; - IsQualificationConversion = true; } else if (S.IsDerivedFrom(Loc, FromType, ClassType)) { SecondKind = ICK_Derived_To_Base; } else if (!Method->isExplicitObjectMemberFunction()) { @@ -6051,8 +6041,6 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( ICS.Standard.setFromType(FromType); ICS.Standard.setAllToTypes(ImplicitParamType); ICS.Standard.ReferenceBinding = true; - ICS.Standard.IsImplicitObjectArgumentQualificationConversion = - IsQualificationConversion; ICS.Standard.DirectBinding = true; ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; ICS.Standard.BindsToFunctionLvalue = false; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f85826aecadf3..f46be75bda20f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2287,7 +2287,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, // we can diagnose if we don't see any variable declarations. This // covers a case like declaring a typedef, function, or structure // type rather than a variable. - NonVarSeen = DI; + // + // Note, _Static_assert is acceptable because it does not declare an + // identifier at all, so "for object having" does not apply. + if (!isa(DI)) + NonVarSeen = DI; } } // Diagnose if we saw a non-variable declaration but no variable diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b76619fc50268..f067aedf1cc9f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4749,8 +4749,6 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, EnterExpressionEvaluationContext EECtx{ *this, ExpressionEvaluationContext::Unevaluated, CSD}; - ContextRAII CurContext(*this, CSD->getDeclContext(), - /*NewThisContext=*/false); if (!AreArgsDependent && CheckConstraintSatisfaction( NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()), diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index d09a72b71b805..ce78ecc2d4a2d 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5525,6 +5525,15 @@ static TemplateDeductionResult CheckDeductionConsistency( // FIXME: A substitution can be incomplete on a non-structural part of the // type. Use the canonical type for now, until the TemplateInstantiator can // deal with that. + + // Workaround: Implicit deduction guides use InjectedClassNameTypes, whereas + // the explicit guides don't. The substitution doesn't transform these types, + // so let it transform their specializations instead. + bool IsDeductionGuide = isa(FTD->getTemplatedDecl()); + if (IsDeductionGuide) { + if (auto *Injected = P->getAs()) + P = Injected->getInjectedSpecializationType(); + } QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(), FTD->getDeclName(), &IsIncompleteSubstitution); if (InstP.isNull() && !IsIncompleteSubstitution) @@ -5539,9 +5548,15 @@ static TemplateDeductionResult CheckDeductionConsistency( if (auto *PA = dyn_cast(A); PA && !isa(InstP)) A = PA->getPattern(); - if (!S.Context.hasSameType( - S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()), - S.Context.getUnqualifiedArrayType(A.getNonReferenceType()))) + auto T1 = S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()); + auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType()); + if (IsDeductionGuide) { + if (auto *Injected = T1->getAs()) + T1 = Injected->getInjectedSpecializationType(); + if (auto *Injected = T2->getAs()) + T2 = Injected->getInjectedSpecializationType(); + } + if (!S.Context.hasSameType(T1, T2)) return TemplateDeductionResult::NonDeducedMismatch; return TemplateDeductionResult::Success; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e2c3cdcd536bc..d2b87f2702a9c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5685,7 +5685,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, }; Function->setDeclarationNameLoc(NameLocPointsToPattern()); - EnterExpressionEvaluationContext EvalContext( + EnterExpressionEvaluationContextForFunction EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); Qualifiers ThisTypeQuals; diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1d8687e4bf1c1..21ba19ee551c0 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1768,7 +1768,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, // Objective-C lifetime, this is a non-trivial assignment. if (LhsT.getNonReferenceType().hasNonTrivialObjCLifetime()) return false; - + ASTContext &Context = Self.getASTContext(); + if (Context.containsAddressDiscriminatedPointerAuth(LhsT) || + Context.containsAddressDiscriminatedPointerAuth(RhsT)) + return false; return !Result.get()->hasNonTrivialCall(Self.Context); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 30e0973149594..3e7ccfdd9db5d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3103,6 +3103,10 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.Kind == MK_ImplicitModule) N = ForceValidateUserInputs ? NumUserInputs : 0; + if (N != 0) + Diag(diag::remark_module_validation) + << N << F.ModuleName << F.FileName; + for (unsigned I = 0; I < N; ++I) { InputFile IF = getInputFile(F, I+1, Complain); if (!IF.getFile() || IF.isOutOfDate()) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1a20fc9595dce..3caf9ebb32185 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4340,8 +4340,7 @@ class ASTDeclContextNameLookupTrait // parent of parent. We DON'T remove the enum constant from its parent. So // we don't need to care about merging problems here. if (auto *ECD = dyn_cast(D); - ECD && DC.isFileContext() && ECD->getOwningModule() && - ECD->getTopLevelOwningNamedModule()->isNamedModule()) { + ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) { if (llvm::all_of( DC.noload_lookup( cast(ECD->getDeclContext())->getDeclName()), diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp index f42bdc16d815d..88ad8dd6495dd 100644 --- a/clang/lib/Serialization/ModuleCache.cpp +++ b/clang/lib/Serialization/ModuleCache.cpp @@ -34,8 +34,10 @@ class CrossProcessModuleCache : public ModuleCache { } std::time_t getModuleTimestamp(StringRef ModuleFilename) override { + std::string TimestampFilename = + serialization::ModuleFile::getTimestampFilename(ModuleFilename); llvm::sys::fs::file_status Status; - if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{}) + if (llvm::sys::fs::status(TimestampFilename, Status) != std::error_code{}) return 0; return llvm::sys::toTimeT(Status.getLastModificationTime()); } diff --git a/clang/lib/StaticAnalyzer/Checkers/AssumeModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/AssumeModeling.cpp index 1e3adb4f266ca..789c7772d123a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AssumeModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AssumeModeling.cpp @@ -45,7 +45,6 @@ void AssumeModelingChecker::checkPostStmt(const AttributedStmt *A, continue; const auto *Assumption = AssumptionVal.getAsInteger(); - assert(Assumption && "We should know the exact outcome of an assume expr"); if (Assumption && Assumption->isZero()) { C.addSink(); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index fa8e669b6bb2f..ab29f86cec326 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -916,7 +916,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, QualType T = Ex->getTypeOfArgument(); for (ExplodedNode *N : CheckedSet) { - if (Ex->getKind() == UETT_SizeOf) { + if (Ex->getKind() == UETT_SizeOf || Ex->getKind() == UETT_DataSizeOf || + Ex->getKind() == UETT_CountOf) { if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 85353848aa124..dc715c7d46d8b 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -71,21 +71,30 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, Bldr.takeNodes(Pred); assert(ThisRD); - SVal V = Call.getArgSVal(0); - const Expr *VExpr = Call.getArgExpr(0); - // If the value being copied is not unknown, load from its location to get - // an aggregate rvalue. - if (std::optional L = V.getAs()) - V = Pred->getState()->getSVal(*L); - else - assert(V.isUnknownOrUndef()); + if (!ThisRD->isEmpty()) { + SVal V = Call.getArgSVal(0); + const Expr *VExpr = Call.getArgExpr(0); - ExplodedNodeSet Tmp; - evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V, - /*isLoad=*/true); - for (ExplodedNode *N : Tmp) - evalBind(Dst, CallExpr, N, ThisVal, V, true); + // If the value being copied is not unknown, load from its location to get + // an aggregate rvalue. + if (std::optional L = V.getAs()) + V = Pred->getState()->getSVal(*L); + else + assert(V.isUnknownOrUndef()); + + ExplodedNodeSet Tmp; + evalLocation(Tmp, CallExpr, VExpr, Pred, Pred->getState(), V, + /*isLoad=*/true); + for (ExplodedNode *N : Tmp) + evalBind(Dst, CallExpr, N, ThisVal, V, true); + } else { + // We can't copy empty classes because of empty base class optimization. + // In that case, copying the empty base class subobject would overwrite the + // object that it overlaps with - so let's not do that. + // See issue-157467.cpp for an example. + Dst.Add(Pred); + } PostStmt PS(CallExpr, LCtx); for (ExplodedNode *N : Dst) { diff --git a/clang/test/ASTMerge/enum/Inputs/enum3.c b/clang/test/ASTMerge/enum/Inputs/enum3.c new file mode 100644 index 0000000000000..32ad5366434ac --- /dev/null +++ b/clang/test/ASTMerge/enum/Inputs/enum3.c @@ -0,0 +1,14 @@ +// [C23] missing underlying types +enum E1 : int { + E1Enumerator1 +}; + +enum E2 { + E2Enumerator1 +}; + +// [C23] Incompatible underlying types +enum E3 : long { + E3Enumerator1 +}; + diff --git a/clang/test/ASTMerge/enum/Inputs/enum4.c b/clang/test/ASTMerge/enum/Inputs/enum4.c new file mode 100644 index 0000000000000..15f5c603c7abb --- /dev/null +++ b/clang/test/ASTMerge/enum/Inputs/enum4.c @@ -0,0 +1,14 @@ +// [C23] missing underlying types +enum E1 { + E1Enumerator1 +}; + +enum E2 : int { + E2Enumerator1 +}; + +// [C23] Incompatible underlying types +enum E3 : short { + E3Enumerator1 +}; + diff --git a/clang/test/ASTMerge/enum/test2.c b/clang/test/ASTMerge/enum/test2.c new file mode 100644 index 0000000000000..bdd8b13ee4c21 --- /dev/null +++ b/clang/test/ASTMerge/enum/test2.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c23 -emit-pch -o %t.1.ast %S/Inputs/enum3.c +// RUN: %clang_cc1 -std=c23 -emit-pch -o %t.2.ast %S/Inputs/enum4.c +// RUN: %clang_cc1 -std=c23 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: enum3.c:2:6: warning: type 'enum E1' has incompatible definitions in different translation units +// CHECK: enum4.c:2:6: note: enumeration 'E1' missing fixed underlying type here +// CHECK: enum3.c:2:6: note: enumeration 'E1' has fixed underlying type here +// CHECK: enum3.c:6:6: warning: type 'enum E2' has incompatible definitions in different translation units +// CHECK: enum4.c:6:6: note: enumeration 'E2' has fixed underlying type here +// CHECK: enum3.c:6:6: note: enumeration 'E2' missing fixed underlying type here +// CHECK: enum3.c:11:6: warning: type 'enum E3' has incompatible definitions in different translation units +// CHECK: enum3.c:11:6: note: enumeration 'E3' declared with incompatible fixed underlying types ('long' vs. 'short') +// CHECK: 3 warnings generated + diff --git a/clang/test/Analysis/ctor-trivial-copy.cpp b/clang/test/Analysis/ctor-trivial-copy.cpp index 45c8ca4c51776..940ff9ba3ed9c 100644 --- a/clang/test/Analysis/ctor-trivial-copy.cpp +++ b/clang/test/Analysis/ctor-trivial-copy.cpp @@ -46,15 +46,10 @@ void _01_empty_structs() { empty Empty = conjure(); empty Empty2 = Empty; empty Empty3 = Empty2; - // All of these should refer to the exact same symbol, because all of - // these trivial copies refer to the original conjured value. - // There were Unknown before: - clang_analyzer_denote(Empty, "$Empty"); - clang_analyzer_express(Empty); // expected-warning {{$Empty}} - clang_analyzer_express(Empty2); // expected-warning {{$Empty}} - clang_analyzer_express(Empty3); // expected-warning {{$Empty}} - // We should have the same Conjured symbol for "Empty", "Empty2" and "Empty3". + // We only have binding for the original Empty object, because copying empty + // objects is a no-op in the performTrivialCopy. This is fine, because empty + // objects don't have any data members that could be accessed anyway. clang_analyzer_printState(); // CHECK: "store": { "pointer": "0x{{[0-9a-f]+}}", "items": [ // CHECK-NEXT: { "cluster": "GlobalInternalSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ @@ -65,12 +60,6 @@ void _01_empty_structs() { // CHECK-NEXT: ]}, // CHECK-NEXT: { "cluster": "Empty", "pointer": "0x{{[0-9a-f]+}}", "items": [ // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[EMPTY_CONJ:conj_\$[0-9]+{int, LC[0-9]+, S[0-9]+, #[0-9]+}]]" } - // CHECK-NEXT: ]}, - // CHECK-NEXT: { "cluster": "Empty2", "pointer": "0x{{[0-9a-f]+}}", "items": [ - // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[EMPTY_CONJ]]" } - // CHECK-NEXT: ]}, - // CHECK-NEXT: { "cluster": "Empty3", "pointer": "0x{{[0-9a-f]+}}", "items": [ - // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[EMPTY_CONJ]]" } // CHECK-NEXT: ]} // CHECK-NEXT: ]}, diff --git a/clang/test/Analysis/cxx23-assume-attribute.cpp b/clang/test/Analysis/cxx23-assume-attribute.cpp index 86e7662cd2af9..4cc16446572dc 100644 --- a/clang/test/Analysis/cxx23-assume-attribute.cpp +++ b/clang/test/Analysis/cxx23-assume-attribute.cpp @@ -69,3 +69,9 @@ int assume_and_fallthrough_at_the_same_attrstmt(int a, int b) { return 0; } + +void assume_opaque_gh151854_no_crash() { + extern bool opaque(); + [[assume(opaque())]]; // no-crash + // expected-warning@-1 {{assumption is ignored because it contains (potential) side-effects}} +} diff --git a/clang/test/Analysis/engine/gh151711.cpp b/clang/test/Analysis/engine/gh151711.cpp new file mode 100644 index 0000000000000..a9950a7a3b9d0 --- /dev/null +++ b/clang/test/Analysis/engine/gh151711.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -x c %s + +void clang_analyzer_dump(int); + +// Ensure that VLA types are correctly handled by unary type traits in the +// expression engine. Previously, __datasizeof and _Countof both caused failed +// assertions. +void gh151711(int i) { + clang_analyzer_dump(sizeof(int[i++])); // expected-warning {{Unknown}} +#ifdef __cplusplus + // __datasizeof is only available in C++. + clang_analyzer_dump(__datasizeof(int[i++])); // expected-warning {{Unknown}} +#else + // _Countof is only available in C. + clang_analyzer_dump(_Countof(int[i++])); // expected-warning {{Unknown}} +#endif +} diff --git a/clang/test/Analysis/issue-157467.cpp b/clang/test/Analysis/issue-157467.cpp new file mode 100644 index 0000000000000..8281ea1ee1aed --- /dev/null +++ b/clang/test/Analysis/issue-157467.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s +// expected-no-diagnostics + +template +struct compressed_pair_elem { + explicit compressed_pair_elem(T u) : value(u) {} + T value; +}; + +template +struct compressed_pair_elem : T { + explicit compressed_pair_elem(T u) : T(u) {} +}; + +template , class Base2 = compressed_pair_elem> +struct compressed_pair : Base1, Base2 { + explicit compressed_pair(T1 t1, T2 t2) : Base1(t1), Base2(t2) {} +}; + +// empty deleter object +template +struct default_delete { + void operator()(T* p) { + delete p; + } +}; + +template > +struct some_unique_ptr { + // compressed_pair will employ the empty base class optimization, thus overlapping + // the `int*` and the empty `Deleter` object, clobbering the pointer. + compressed_pair ptr; + some_unique_ptr(int* p, Deleter d) : ptr(p, d) {} + ~some_unique_ptr(); +}; + +void entry_point() { + some_unique_ptr > u3(new int(12), default_delete()); +} diff --git a/clang/test/Analysis/taint-generic.cpp b/clang/test/Analysis/taint-generic.cpp index c080313e4d172..fc7c37300d3fc 100644 --- a/clang/test/Analysis/taint-generic.cpp +++ b/clang/test/Analysis/taint-generic.cpp @@ -153,8 +153,9 @@ void top() { int Int = mySource1(); clang_analyzer_isTainted(Int); // expected-warning {{YES}} + // It's fine to not propagate taint to empty classes, since they don't have any data members. Empty E = mySource1(); - clang_analyzer_isTainted(E); // expected-warning {{YES}} + clang_analyzer_isTainted(E); // expected-warning {{NO}} Aggr A = mySource1(); clang_analyzer_isTainted(A); // expected-warning {{YES}} diff --git a/clang/test/C/C23/n3037.c b/clang/test/C/C23/n3037.c index ce6f4c4ea7acf..d5699e2df1421 100644 --- a/clang/test/C/C23/n3037.c +++ b/clang/test/C/C23/n3037.c @@ -401,3 +401,77 @@ _Static_assert(0 == _Generic(inner_anon_tagged.untagged, struct { int i; } : 1, // unions and structures are both RecordDecl objects, whereas EnumDecl is not). enum { E_Untagged1 } nontag_enum; // both-note {{previous definition is here}} _Static_assert(0 == _Generic(nontag_enum, enum { E_Untagged1 } : 1, default : 0)); // both-error {{redefinition of enumerator 'E_Untagged1'}} + +// Test that enumerations are compatible with their underlying type, but still +// diagnose when "same type" is required rather than merely "compatible type". +enum E1 : int { e1 }; // Fixed underlying type +enum E2 { e2 }; // Unfixed underlying type, defaults to int or unsigned int + +struct GH149965_1 { int h; }; +// This typeof trick is used to get the underlying type of the enumeration in a +// platform agnostic way. +struct GH149965_2 { __typeof__(+(enum E2){}) h; }; +void gh149965(void) { + extern struct GH149965_1 x1; // c17-note {{previous declaration is here}} + extern struct GH149965_2 x2; // c17-note {{previous declaration is here}} + + // Both the structure and the variable declarations are fine because only a + // compatible type is required, not the same type, because the structures are + // declared in different scopes. + struct GH149965_1 { enum E1 h; }; + struct GH149965_2 { enum E2 h; }; + + extern struct GH149965_1 x1; // c17-error {{redeclaration of 'x1'}} + extern struct GH149965_2 x2; // c17-error {{redeclaration of 'x2'}} + + // However, in the same scope, the same type is required, not just compatible + // types. + // FIXME: this should be an error in both C17 and C23 mode. + struct GH149965_3 { int h; }; // c17-note {{previous definition is here}} + struct GH149965_3 { enum E1 h; }; // c17-error {{redefinition of 'GH149965_3'}} + + // For Clang, the composite type after declaration merging is the enumeration + // type rather than an integer type. + enum E1 *eptr; + [[maybe_unused]] __typeof__(x1.h) *ptr = eptr; + enum E2 *eptr2; + [[maybe_unused]] __typeof__(x2.h) *ptr2 = eptr2; +} + +// Test that enumerations with mixed underlying types are properly handled. +enum GH150594_E1 : int { GH150594_Val1 }; +enum GH150594_E2 : int { GH150594_Val2 }; +enum GH150594_E3 { GH150594_Val3 }; +enum GH150594_E4 : int { GH150594_Val4 }; +void GH150594(void) { + extern enum GH150594_E1 Fn1(void); // both-note {{previous declaration is here}} + extern enum GH150594_E2 Fn2(void); // c17-note {{previous declaration is here}} + extern enum GH150594_E3 Fn3(void); // both-note {{previous declaration is here}} + extern enum GH150594_E4 Fn4(void); // both-note {{previous declaration is here}} + enum GH150594_E1 { GH150594_Val1 }; + enum GH150594_E2 : int { GH150594_Val2 }; + enum GH150594_E3 : int { GH150594_Val3 }; + enum GH150594_E4 : short { GH150594_Val4 }; + extern enum GH150594_E1 Fn1(void); // both-error {{conflicting types for 'Fn1'}} + extern enum GH150594_E2 Fn2(void); // c17-error {{conflicting types for 'Fn2'}} + extern enum GH150594_E3 Fn3(void); // both-error {{conflicting types for 'Fn3'}} + extern enum GH150594_E4 Fn4(void); // both-error {{conflicting types for 'Fn4'}} + + // Show that two declarations in the same scope give expected diagnostics. + enum E1 { e1 }; // both-note {{previous declaration is here}} + enum E1 : int { e1 }; // both-error {{enumeration previously declared with nonfixed underlying type}} + + enum E2 : int { e2 }; // both-note {{previous declaration is here}} + enum E2 { e2 }; // both-error {{enumeration previously declared with fixed underlying type}} + + enum E3 : int { e3 }; // both-note {{previous declaration is here}} + enum E3 : short { e3 }; // both-error {{enumeration redeclared with different underlying type 'short' (was 'int')}} + + typedef short foo; + enum E4 : foo { e4 }; // c17-note 2 {{previous definition is here}} + enum E4 : short { e4 }; // c17-error {{redefinition of 'E4'}} \ + c17-error {{redefinition of enumerator 'e4'}} + + enum E5 : foo { e5 }; // both-note {{previous declaration is here}} + enum E5 : int { e5 }; // both-error {{enumeration redeclared with different underlying type 'int' (was 'foo' (aka 'short'))}} +} diff --git a/clang/test/C/C2y/n3353.c b/clang/test/C/C2y/n3353.c index cd61cbf039067..a2e08cf6344db 100644 --- a/clang/test/C/C2y/n3353.c +++ b/clang/test/C/C2y/n3353.c @@ -44,7 +44,12 @@ static const void *ptr = 0o0; /* ext-warning {{octal integer literals are a C2y #endif // 0 by itself is not deprecated, of course. -int k = 0; +int k1 = 0; +unsigned int k2 = 0u; +long k3 = 0l; +unsigned long k4 = 0ul; +long long k5 = 0ll; +unsigned long long k6 = 0ull; // Test a preprocessor use of 0 by itself, which is also not deprecated. #if 0 @@ -65,7 +70,6 @@ static_assert(__extension__ _Generic(typeof(l), const int : 1, default : 0)); // // Note that 0o by itself is an invalid literal. int m = 0o; /* expected-error {{invalid suffix 'o' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Ensure negation works as expected. @@ -83,13 +87,11 @@ int n = 0o18; /* expected-error {{invalid digit '8' in octal constant}} cpp-warning {{octal integer literals are a Clang extension}} */ int o1 = 0o8; /* expected-error {{invalid suffix 'o8' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // FIXME: however, it matches the behavior for hex literals in terms of the // error reported. Unfortunately, we then go on to think 0 is an octal literal // without a prefix, which is again a bit confusing. int o2 = 0xG; /* expected-error {{invalid suffix 'xG' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ // Show that floating-point suffixes on octal literals are rejected. @@ -130,7 +132,6 @@ constexpr int p = 0o0'1'2'3'4'5'6'7; /* compat-warning {{octal integer literals */ static_assert(p == 01234567); // c2y-warning {{octal literals without a '0o' prefix are deprecated}} int q = 0o'0'1; /* expected-error {{invalid suffix 'o'0'1' on integer constant}} - c2y-warning {{octal literals without a '0o' prefix are deprecated}} */ #define M 0o123 diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 58080014abc50..286c9d40d2dab 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -226,17 +226,6 @@ add_custom_target(clang-test) add_dependencies(clang-test check-clang) set_target_properties(clang-test PROPERTIES FOLDER "Clang/Tests") -# Allow running Clang Python binding tests separately from CI. -add_lit_testsuite(check-clang-python "Running the Clang Python tests" - ${CMAKE_CURRENT_BINARY_DIR} - #LIT ${LLVM_LIT} - PARAMS ${CLANG_TEST_PARAMS} - DEPENDS ${CLANG_TEST_DEPS} - ARGS ${CLANG_TEST_EXTRA_ARGS} --filter=bindings.sh - # Avoid running tests twice. - EXCLUDE_FROM_CHECK_ALL - ) - # FIXME: This logic can be removed once all buildbots have moved # debuginfo-test from clang/test to llvm/projects or monorepo. if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/debuginfo-tests) diff --git a/clang/test/CXX/module/cpp.pre/module_decl.cpp b/clang/test/CXX/module/cpp.pre/module_decl.cpp index 6238347c167ac..5c29aeff1b632 100644 --- a/clang/test/CXX/module/cpp.pre/module_decl.cpp +++ b/clang/test/CXX/module/cpp.pre/module_decl.cpp @@ -1,8 +1,147 @@ // RUN: rm -rf %t // RUN: mkdir -p %t -// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o %t/M.pcm +// RUN: split-file %s %t +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/line.cpp -verify -o %t/line.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/gnu_line_marker.cpp -verify -o %t/gnu_line_marker.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/include.cpp -verify -o %t/include.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/ident.cpp -verify -o %t/ident.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_comment.cpp -verify -o %t/pragma_comment.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_mark.cpp -verify -o %t/pragma_mark.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_detect_mismatch.cpp -verify -o %t/pragma_detect_mismatch.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_debug.cpp -verify -o %t/pragma_clang_debug.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_message.cpp -verify -o %t/pragma_message.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_warn.cpp -verify -o %t/pragma_gcc_warn.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_gcc_error.cpp -verify -o %t/pragma_gcc_error.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_push_pop.cpp -verify -o %t/pragma_diag_push_pop.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_diag_ignore.cpp -verify -o %t/pragma_diag_ignore.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_opencl_ext.cpp -verify -o %t/pragma_opencl_ext.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_push_pop.cpp -verify -o %t/pragma_push_pop.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_exec_charset.cpp -verify -o %t/pragma_exec_charset.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/pragma_clang_assume_nonnull.cpp -verify -o %t/pragma_clang_assume_nonnull.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/marco_expand.cpp -DMACRO="" -verify -o %t/marco_expand.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/define.cpp -verify -o %t/define.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/undef.cpp -verify -o %t/undef.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/defined.cpp -verify -o %t/defined.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_embed.cpp -verify -o %t/has_embed.pcm +// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/has_include.cpp -verify -o %t/has_include.pcm +//--- header.h +#ifndef HEADER_H +#define HEADER_H + +#endif // HEADER_H + +//--- line.cpp +// expected-no-diagnostics +#line 3 +export module M; + +//--- gnu_line_marker.cpp +// expected-no-diagnostics +# 1 __FILE__ 1 3 +export module M; + +//--- include.cpp +#include "header.h" // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} + +//--- ident.cpp +// expected-no-diagnostics +#ident "$Header:$" +export module M; + +//--- pragma_comment.cpp +// expected-no-diagnostics +#pragma comment(lib, "msvcrt.lib") +export module M; + +//--- pragma_mark.cpp +// expected-no-diagnostics +#pragma mark LLVM's world +export module M; + +//--- pragma_detect_mismatch.cpp +// expected-no-diagnostics +#pragma detect_mismatch("test", "1") +export module M; + +//--- pragma_clang_debug.cpp +// expected-no-diagnostics +#pragma clang __debug dump Test +export module M; + +//--- pragma_message.cpp +#pragma message "test" // expected-warning {{test}} +export module M; + +//--- pragma_gcc_warn.cpp +#pragma GCC warning "Foo" // expected-warning {{Foo}} +export module M; + +//--- pragma_gcc_error.cpp +#pragma GCC error "Foo" // expected-error {{Foo}} +export module M; + +//--- pragma_diag_push_pop.cpp +// expected-no-diagnostics +#pragma gcc diagnostic push +#pragma gcc diagnostic pop +export module M; + +//--- pragma_diag_ignore.cpp +// expected-no-diagnostics +#pragma GCC diagnostic ignored "-Wframe-larger-than" +export module M; + +//--- pragma_opencl_ext.cpp +// expected-no-diagnostics +#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable +export module M; + +//--- pragma_push_pop.cpp +// expected-no-diagnostics +#pragma warning(push) +#pragma warning(pop) +export module M; + +//--- pragma_exec_charset.cpp +// expected-no-diagnostics +#pragma execution_character_set(push, "UTF-8") +#pragma execution_character_set(pop) +export module M; + +//--- pragma_clang_assume_nonnull.cpp +// expected-no-diagnostics +#pragma clang assume_nonnull begin +#pragma clang assume_nonnull end +export module M; + +//--- marco_expand.cpp +MACRO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} + +//--- define.cpp // This is a comment #define I32 int // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} export module M; // expected-error {{module declaration must occur at the start of the translation unit}} export I32 i32; + +//--- undef.cpp +#undef FOO // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} + +//--- defined.cpp +#if defined(FOO) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} +#endif +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} + +//--- has_embed.cpp +#if __has_embed(__FILE__ ext::token(0xB055)) // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} +#endif +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} + +//--- has_include.cpp +#if __has_include() || __has_include_next() // expected-note {{add 'module;' to the start of the file to introduce a global module fragment}} \ + // expected-warning {{#include_next in primary source file; will search from start of include path}} +#endif +export module M; // expected-error {{module declaration must occur at the start of the translation unit}} diff --git a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp index abb42447d3e0b..05830de9891fe 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp @@ -239,5 +239,21 @@ void f2() { } +namespace GH153884 { + bool f1() { + auto f = [](auto) { return true; }; + if constexpr (0) + return f(1); + return false; + } + bool f2() { + auto f = [](auto x) { if (x) return 1.5; else return "wat"; }; + // expected-error@-1 {{'auto' in return type deduced as 'const char *' here but deduced as 'double' in earlier return statement}} + if constexpr (0) + return f(1); + // expected-note@-1 {{in instantiation of function template specialization 'GH153884::f2()}} + return false; + } +} #endif diff --git a/clang/test/CodeGen/LoongArch/targetattr-lasx.c b/clang/test/CodeGen/LoongArch/targetattr-lasx.c new file mode 100644 index 0000000000000..56fd6573ed34c --- /dev/null +++ b/clang/test/CodeGen/LoongArch/targetattr-lasx.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple loongarch64 -target-feature -lsx -emit-llvm %s -o - | FileCheck %s + +__attribute__((target("lasx"))) +// CHECK: #[[ATTR0:[0-9]+]] { +void testlasx() {} + +// CHECK: attributes #[[ATTR0]] = { {{.*}}"target-features"="+64bit,+lasx,+lsx"{{.*}} } diff --git a/clang/test/CodeGen/X86/avx10_2_512ni-builtins.c b/clang/test/CodeGen/X86/avx10_2_512ni-builtins.c index 26e0d124c8284..d143188ee0f31 100644 --- a/clang/test/CodeGen/X86/avx10_2_512ni-builtins.c +++ b/clang/test/CodeGen/X86/avx10_2_512ni-builtins.c @@ -187,12 +187,12 @@ __m512i test_mm512_mask_dpwsud_epi32(__m512i __A, __mmask16 __B, __m512i __C, __ return _mm512_mask_dpwsud_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwsud_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwsud_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwsud_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwsud.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwsud_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwsud_epi32(__U, __A, __B, __C); } __m512i test_mm512_dpwsuds_epi32(__m512i __A, __m512i __B, __m512i __C) { @@ -208,12 +208,12 @@ __m512i test_mm512_mask_dpwsuds_epi32(__m512i __A, __mmask16 __B, __m512i __C, _ return _mm512_mask_dpwsuds_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwsuds_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwsuds_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwsuds_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwsuds.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwsuds_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwsuds_epi32(__U, __A, __B, __C); } __m512i test_mm512_dpwusd_epi32(__m512i __A, __m512i __B, __m512i __C) { @@ -229,12 +229,12 @@ __m512i test_mm512_mask_dpwusd_epi32(__m512i __A, __mmask16 __B, __m512i __C, __ return _mm512_mask_dpwusd_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwusd_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwusd_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwusd_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwusd.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwusd_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwusd_epi32(__U, __A, __B, __C); } __m512i test_mm512_dpwusds_epi32(__m512i __A, __m512i __B, __m512i __C) { @@ -250,12 +250,12 @@ __m512i test_mm512_mask_dpwusds_epi32(__m512i __A, __mmask16 __B, __m512i __C, _ return _mm512_mask_dpwusds_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwusds_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwusds_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwusds_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwusds.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwusds_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwusds_epi32(__U, __A, __B, __C); } __m512i test_mm512_dpwuud_epi32(__m512i __A, __m512i __B, __m512i __C) { @@ -271,12 +271,12 @@ __m512i test_mm512_mask_dpwuud_epi32(__m512i __A, __mmask16 __B, __m512i __C, __ return _mm512_mask_dpwuud_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwuud_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwuud_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwuud_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwuud.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwuud_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwuud_epi32(__U, __A, __B, __C); } __m512i test_mm512_dpwuuds_epi32(__m512i __A, __m512i __B, __m512i __C) { @@ -292,10 +292,10 @@ __m512i test_mm512_mask_dpwuuds_epi32(__m512i __A, __mmask16 __B, __m512i __C, _ return _mm512_mask_dpwuuds_epi32(__A, __B, __C, __D); } -__m512i test_mm512_maskz_dpwuuds_epi32(__m512i __A, __mmask16 __B, __m512i __C, __m512i __D) { +__m512i test_mm512_maskz_dpwuuds_epi32(__mmask16 __U, __m512i __A, __m512i __B, __m512i __C) { // CHECK-LABEL: @test_mm512_maskz_dpwuuds_epi32( // CHECK: call <16 x i32> @llvm.x86.avx10.vpdpwuuds.512(<16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}) // CHECK: zeroinitializer // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} - return _mm512_maskz_dpwuuds_epi32(__A, __B, __C, __D); + return _mm512_maskz_dpwuuds_epi32(__U, __A, __B, __C); } diff --git a/clang/test/CodeGen/X86/avx10_2ni-builtins.c b/clang/test/CodeGen/X86/avx10_2ni-builtins.c index 936be27da61d7..b4b12c9531942 100644 --- a/clang/test/CodeGen/X86/avx10_2ni-builtins.c +++ b/clang/test/CodeGen/X86/avx10_2ni-builtins.c @@ -264,11 +264,11 @@ __m128i test_mm_mask_dpwsud_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128 return _mm_mask_dpwsud_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwsud_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwsud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwsud_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwsud.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwsud_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwsud_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwsud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -278,11 +278,11 @@ __m256i test_mm256_mask_dpwsud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m return _mm256_mask_dpwsud_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwsud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwsud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwsud_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwsud.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwsud_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwsud_epi32(__U, __A, __B, __C); } __m128i test_mm_mask_dpwsuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { @@ -292,11 +292,11 @@ __m128i test_mm_mask_dpwsuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m12 return _mm_mask_dpwsuds_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwsuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwsuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwsuds_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwsuds.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwsuds_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwsuds_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwsuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -306,11 +306,11 @@ __m256i test_mm256_mask_dpwsuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __ return _mm256_mask_dpwsuds_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwsuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwsuds_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwsuds_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwsuds.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwsuds_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwsuds_epi32(__U, __A, __B, __C); } __m128i test_mm_mask_dpwusd_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { @@ -320,11 +320,11 @@ __m128i test_mm_mask_dpwusd_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128 return _mm_mask_dpwusd_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwusd_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwusd_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwusd_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwusd.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwusd_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwusd_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwusd_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -334,11 +334,11 @@ __m256i test_mm256_mask_dpwusd_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m return _mm256_mask_dpwusd_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwusd_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwusd_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwusd_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwusd.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwusd_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwusd_epi32(__U, __A, __B, __C); } __m128i test_mm_mask_dpwusds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { @@ -348,11 +348,11 @@ __m128i test_mm_mask_dpwusds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m12 return _mm_mask_dpwusds_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwusds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwusds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwusds_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwusds.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwusds_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwusds_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwusds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -362,11 +362,11 @@ __m256i test_mm256_mask_dpwusds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __ return _mm256_mask_dpwusds_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwusds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwusds_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwusds_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwusds.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwusds_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwusds_epi32(__U, __A, __B, __C); } __m128i test_mm_mask_dpwuud_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { @@ -376,11 +376,11 @@ __m128i test_mm_mask_dpwuud_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128 return _mm_mask_dpwuud_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwuud_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwuud_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwuud_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwuud.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwuud_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwuud_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwuud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -390,11 +390,11 @@ __m256i test_mm256_mask_dpwuud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m return _mm256_mask_dpwuud_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwuud_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwuud_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwuud_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwuud.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwuud_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwuud_epi32(__U, __A, __B, __C); } __m128i test_mm_mask_dpwuuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { @@ -404,11 +404,11 @@ __m128i test_mm_mask_dpwuuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m12 return _mm_mask_dpwuuds_epi32(__A, __B, __C, __D); } -__m128i test_mm_maskz_dpwuuds_epi32(__m128i __A, __mmask8 __B, __m128i __C, __m128i __D) { +__m128i test_mm_maskz_dpwuuds_epi32(__mmask8 __U, __m128i __A, __m128i __B, __m128i __C) { // CHECK-LABEL: @test_mm_maskz_dpwuuds_epi32( // CHECK: call <4 x i32> @llvm.x86.avx2.vpdpwuuds.128(<4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}) // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}} - return _mm_maskz_dpwuuds_epi32(__A, __B, __C, __D); + return _mm_maskz_dpwuuds_epi32(__U, __A, __B, __C); } __m256i test_mm256_mask_dpwuuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { @@ -418,9 +418,9 @@ __m256i test_mm256_mask_dpwuuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __ return _mm256_mask_dpwuuds_epi32(__A, __B, __C, __D); } -__m256i test_mm256_maskz_dpwuuds_epi32(__m256i __A, __mmask8 __B, __m256i __C, __m256i __D) { +__m256i test_mm256_maskz_dpwuuds_epi32(__mmask8 __U, __m256i __A, __m256i __B, __m256i __C) { // CHECK-LABEL: @test_mm256_maskz_dpwuuds_epi32( // CHECK: call <8 x i32> @llvm.x86.avx2.vpdpwuuds.256(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}) // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}} - return _mm256_maskz_dpwuuds_epi32(__A, __B, __C, __D); + return _mm256_maskz_dpwuuds_epi32(__U, __A, __B, __C); } diff --git a/clang/test/CodeGen/mangle-windows.c b/clang/test/CodeGen/mangle-windows.c index 046b1e8815a8a..e1b06e72a9635 100644 --- a/clang/test/CodeGen/mangle-windows.c +++ b/clang/test/CodeGen/mangle-windows.c @@ -1,8 +1,10 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-cygwin | FileCheck %s // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-windows-msvc-elf | FileCheck %s --check-prefix=ELF32 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=X64 -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-mingw32 | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-mingw32 | FileCheck %s --check-prefix=X64 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-cygwin | FileCheck %s --check-prefix=X64 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc-elf | FileCheck %s --check-prefix=ELF64 // CHECK: target datalayout = "e-m:x-{{.*}}" diff --git a/clang/test/CodeGen/ptrauth-qualifier-blocks.c b/clang/test/CodeGen/ptrauth-qualifier-blocks.c index 62da59cf327f6..f460da205cac7 100644 --- a/clang/test/CodeGen/ptrauth-qualifier-blocks.c +++ b/clang/test/CodeGen/ptrauth-qualifier-blocks.c @@ -82,9 +82,15 @@ void test_block_address_byref_capture() { // CHECK: store i32 33554432, // CHECK: store i32 48, // CHECK: [[COPY_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 4 - // CHECK: store ptr @__Block_byref_object_copy_, ptr [[COPY_HELPER_FIELD]], align + // CHECK: [[T0:%.*]] = ptrtoint ptr [[COPY_HELPER_FIELD]] to i64 + // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_copy_ to i64), i32 0, i64 [[T0]]) + // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK: store ptr [[T2]], ptr [[COPY_HELPER_FIELD]], align // CHECK: [[DISPOSE_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 5 - // CHECK: store ptr @__Block_byref_object_dispose_, ptr [[DISPOSE_HELPER_FIELD]], align + // CHECK: [[T0:%.*]] = ptrtoint ptr [[DISPOSE_HELPER_FIELD]] to i64 + // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_dispose_ to i64), i32 0, i64 [[T0]]) + // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK: store ptr [[T2]], ptr [[DISPOSE_HELPER_FIELD]], align // flags - copy/dispose required // CHECK: store i32 1107296256, ptr __block struct A * __ptrauth(1, 1, 60) ptr = createA(); diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c index 616e24e7c519d..986413703badd 100644 --- a/clang/test/CodeGen/sparcv9-abi.c +++ b/clang/test/CodeGen/sparcv9-abi.c @@ -25,12 +25,35 @@ long double f_ld(long double x) { return x; } struct empty {}; struct emptyarr { struct empty a[10]; }; +// In 16-byte structs, 16-byte aligned members are expanded +// to their corresponding i128/f128 types. +struct align16_int { _Alignas(16) int x; }; +struct align16_mixed { _Alignas(16) int x; double y; }; +struct align16_longdouble { long double x; }; + // CHECK-LABEL: define{{.*}} i64 @f_empty(i64 %x.coerce) struct empty f_empty(struct empty x) { return x; } // CHECK-LABEL: define{{.*}} i64 @f_emptyarr(i64 %x.coerce) struct empty f_emptyarr(struct emptyarr x) { return x.a[0]; } +// CHECK-LABEL: define{{.*}} void @f_aligncaller(i64 %a.coerce0, i64 %a.coerce1) +// CHECK-LABEL: declare{{.*}} void @f_aligncallee(i32 noundef signext, i64, i64, i64) +void f_aligncallee(int pad, struct align16_int a); +void f_aligncaller(struct align16_int a) { + f_aligncallee(0, a); +} + +// CHECK-LABEL: define{{.*}} double @f_mixed_aligned(i64 noundef %a, i64 %0, i64 %b.coerce0, double %b.coerce1) +double f_mixed_aligned(long a, struct align16_mixed b) { + return b.y; +} + +// CHECK-LABEL: define{{.*}} fp128 @f_longdouble(i64 noundef %a, i64 %0, fp128 %b.coerce) +long double f_longdouble(long a, struct align16_longdouble b) { + return b.x; +} + // CHECK-LABEL: define{{.*}} i64 @f_emptyvar(i32 noundef zeroext %count, ...) long f_emptyvar(unsigned count, ...) { long ret; @@ -80,6 +103,11 @@ struct medium { int *c, *d; }; +struct medium_aligned { + _Alignas(16) int *a; + int *b, *c, *d; +}; + // CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr noundef %x) struct medium f_medium(struct medium x) { x.a += *x.b; @@ -87,6 +115,13 @@ struct medium f_medium(struct medium x) { return x; } +// CHECK-LABEL: define{{.*}} %struct.medium_aligned @f_medium_aligned(ptr noundef %x) +struct medium_aligned f_medium_aligned(struct medium_aligned x) { + x.a += *x.b; + x.b = 0; + return x; +} + // Large structs are also returned indirectly. struct large { int *a, *b; @@ -101,6 +136,15 @@ struct large f_large(struct large x) { return x; } +// Large returns are converted into a pointer argument. +// Such conversion should preserve the alignment of overaligned arguments. +// define{{.*}} void @f_largereturn_aligned(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, i64 %0, i64 %x.coerce0, i64 %x.coerce1) +struct large f_largereturn_aligned(struct align16_int x) { + struct large ret; + ret.x = x.x; + return ret; +} + // A 64-bit struct fits in a register. struct reg { int a, b; @@ -215,6 +259,18 @@ int f_variable(char *f, ...) { case 'm': s += *va_arg(ap, struct medium).a; break; + +// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap +// CHECK-DAG: %[[TMP:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 +// CHECK-DAG: %[[ALIGNED:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP]], i64 -16) +// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGNED]], i64 16 +// CHECK-DAG: store ptr %[[NXT]], ptr %ap +// CHECK-DAG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 {{.*}}, ptr align 16 %[[ALIGNED]], i64 16, i1 false) +// CHECK: br + case 'a': + s += va_arg(ap, struct align16_int).x; + break; } + va_end(ap); return s; } diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp index 0bc4fdaa565c3..aa24a63c58cb8 100644 --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -99,12 +99,12 @@ int main(int argc, char **argv) { return 0; } -// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK %s -// RUN: %clang_cc1 -triple i686-cygwin -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK %s -// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK %s -// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK %s -// RUN: %clang_cc1 -triple i686-cygwin -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK %s -// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK %s +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK -check-prefix=CHECKELF %s +// RUN: %clang_cc1 -triple i686-cygwin -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK -check-prefix=CHECKCOFF %s +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -debug-info-kind=limited -fexceptions -std=c++98 %s -o - | FileCheck -check-prefix=CHECK98 -check-prefix=CHECK -check-prefix=CHECKELF %s +// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK -check-prefix=CHECKELF %s +// RUN: %clang_cc1 -triple i686-cygwin -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK -check-prefix=CHECKCOFF %s +// RUN: %clang_cc1 -triple armv7l-unknown-linux-gnueabihf -emit-llvm -debug-info-kind=limited -fexceptions -std=c++11 %s -o - | FileCheck -check-prefix=CHECK11 -check-prefix=CHECK -check-prefix=CHECKELF %s // CHECK98: invoke {{.+}} @_ZN1BD1Ev(ptr {{[^,]*}} %b) // CHECK98-NEXT: unwind label %{{.+}}, !dbg ![[EXCEPTLOC:.*]] @@ -122,6 +122,14 @@ int main(int argc, char **argv) { // CHECK-SAME: ){{$}} // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" +// CHECKCOFF: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECKCOFF: !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECKCOFF: !DICompositeType(tag: DW_TAG_union_type, name: "baz" +// CHECKCOFF: !DICompositeType(tag: DW_TAG_class_type, name: "B" +// CHECKCOFF-NOT: DIFlagFwdDecl +// CHECKCOFF-SAME: ){{$}} +// CHECKCOFF: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", +// CHECKCOFF-SAME: DIFlagArtificial // CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-NOT: DIFlagFwdDecl @@ -137,19 +145,19 @@ int main(int argc, char **argv) { // CHECK-SAME: DIFlagStaticMember // CHECK: [[C_DTOR]] = !DISubprogram(name: "~C" -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "K" -// CHECK-SAME: identifier: "_ZTS1K" -// CHECK-SAME: ){{$}} +// CHECKELF: !DICompositeType(tag: DW_TAG_structure_type, name: "K" +// CHECKELF-SAME: identifier: "_ZTS1K" +// CHECKELF-SAME: ){{$}} -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", -// CHECK-SAME: DIFlagArtificial +// CHECKELF: !DICompositeType(tag: DW_TAG_class_type, name: "B" +// CHECKELF-NOT: DIFlagFwdDecl +// CHECKELF-SAME: ){{$}} +// CHECKELF: !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", +// CHECKELF-SAME: DIFlagArtificial -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar" -// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz" +// CHECKELF: !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECKELF: !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECKELF: !DICompositeType(tag: DW_TAG_union_type, name: "baz" // CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D" // CHECK-SAME: size: @@ -162,6 +170,10 @@ int main(int argc, char **argv) { // CHECK-NOT: identifier: // CHECK-SAME: ){{$}} +// CHECKCOFF: !DICompositeType(tag: DW_TAG_structure_type, name: "K" +// CHECKCOFF-SAME: identifier: "_ZTS1K" +// CHECKCOFF-SAME: ){{$}} + // CHECK: [[L:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "L" // CHECK-SAME: ){{$}} // CHECK: [[L_FUNC_DECL:![0-9]*]] = !DISubprogram(name: "func",{{.*}} scope: [[L]] diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp index 5fbd54c16382c..8032ce85c9e25 100644 --- a/clang/test/CodeGenCXX/debug-info-structured-binding.cpp +++ b/clang/test/CodeGenCXX/debug-info-structured-binding.cpp @@ -7,6 +7,12 @@ // CHECK: #dbg_declare(ptr %{{[0-9]+}}, ![[VAR_4:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 4), // CHECK: #dbg_declare(ptr %z1, ![[VAR_5:[0-9]+]], !DIExpression() // CHECK: #dbg_declare(ptr %z2, ![[VAR_6:[0-9]+]], !DIExpression() +// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg ![[Y1_DEBUG_LOC:[0-9]+]] +// CHECK: getelementptr inbounds nuw %struct.A, ptr {{.*}}, i32 0, i32 1, !dbg ![[Y2_DEBUG_LOC:[0-9]+]] +// CHECK: load ptr, ptr %z2, {{.*}}!dbg ![[Z2_DEBUG_LOC:[0-9]+]] +// CHECK: getelementptr inbounds [2 x i32], ptr {{.*}}, i{{64|32}} 0, i{{64|32}} 1, !dbg ![[A2_DEBUG_LOC:[0-9]+]] +// CHECK: getelementptr inbounds nuw { i32, i32 }, ptr {{.*}}, i32 0, i32 1, !dbg ![[C2_DEBUG_LOC:[0-9]+]] +// CHECK: extractelement <2 x i32> {{.*}}, i32 1, !dbg ![[V2_DEBUG_LOC:[0-9]+]] // CHECK: ![[VAR_0]] = !DILocalVariable(name: "a" // CHECK: ![[VAR_1]] = !DILocalVariable(name: "x1", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) // CHECK: ![[VAR_2]] = !DILocalVariable(name: "y1", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) @@ -46,5 +52,41 @@ int f() { auto [x1, y1] = a; auto &[x2, y2] = a; auto [z1, z2] = B{1, 2}; - return x1 + y1 + x2 + y2 + z1 + z2; + int array[2] = {3, 4}; + auto &[a1, a2] = array; + _Complex int cmplx = {1, 2}; + auto &[c1, c2] = cmplx; + int vctr __attribute__ ((vector_size (sizeof(int)*2)))= {1, 2}; + auto &[v1, v2] = vctr; + return // + x1 // + + // +// CHECK: ![[Y1_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + y1 // + + // + x2 // + + // +// CHECK: ![[Y2_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + y2 // + + // + z1 // + + // +// CHECK: ![[Z2_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + z2 // + + // + a1 // + + // +// CHECK: ![[A2_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + a2 // + + // + c1 // + + // +// CHECK: ![[C2_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + c2 // + + // + v1 // + + // +// CHECK: ![[V2_DEBUG_LOC]] = !DILocation(line: [[@LINE+1]] + v2 // + ; } diff --git a/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp b/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp index 9a8ce1997a7f9..19c2a9bd0497e 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fvisibility=hidden -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fapple-kext -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fno-assume-unique-vtables -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT +// RUN: %clang_cc1 -I%S %s -triple arm64e-apple-darwin10 -O1 -fptrauth-calls -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT struct A { virtual ~A(); }; struct B final : A { }; diff --git a/clang/test/CodeGenCXX/mangle-windows.cpp b/clang/test/CodeGenCXX/mangle-windows.cpp index 3d5a1e9a868ef..737abcf6e3498 100644 --- a/clang/test/CodeGenCXX/mangle-windows.cpp +++ b/clang/test/CodeGenCXX/mangle-windows.cpp @@ -4,6 +4,9 @@ // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-mingw32 | \ // RUN: FileCheck --check-prefix=ITANIUM %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-cygwin | \ +// RUN: FileCheck --check-prefix=ITANIUM %s + void __stdcall f1(void) {} // WIN: define dso_local x86_stdcallcc void @"?f1@@YGXXZ" // ITANIUM: define dso_local x86_stdcallcc void @"\01__Z2f1v@0" diff --git a/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp b/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp index 1b103719fbe46..e33525c1ec0f9 100644 --- a/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp +++ b/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp @@ -1,31 +1,31 @@ -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s @@ -78,6 +78,27 @@ struct authenticated(default_key, default_address_discrimination, custom_discrim virtual void g(); }; +// CHECK: @_ZTVN5test19ConstEvalE = external unnamed_addr constant { [3 x ptr] }, align 8 +// CHECK: @_ZN5test12ceE = global %{{.*}} { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test19ConstEvalE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test12ceE) }, align 8 +// CHECK: @_ZTVN5test116ConstEvalDerivedE = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTIN5test116ConstEvalDerivedE, ptr ptrauth (ptr @_ZN5test19ConstEval1fEv, i32 0, i64 26259, ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2))] },{{.*}}align 8 +// CHECK: @_ZN5test13cedE = global { ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test13cedE) }, align 8 + +struct authenticated(default_key, address_discrimination, no_extra_discrimination) ConstEval { + consteval ConstEval() {} + virtual void f(); +}; + +// clang used to bail out with error message "could not emit constant value abstractly". +ConstEval ce; + +struct ConstEvalDerived : public ConstEval { +public: + consteval ConstEvalDerived() {} +}; + +// clang used to emit an undef initializer. +ConstEvalDerived ced; + template struct SubClass : T { virtual void g(); diff --git a/clang/test/CodeGenCXX/sizeof-unwind-exception.cpp b/clang/test/CodeGenCXX/sizeof-unwind-exception.cpp index 4fb977a5367e7..e40b2d7ae43ea 100644 --- a/clang/test/CodeGenCXX/sizeof-unwind-exception.cpp +++ b/clang/test/CodeGenCXX/sizeof-unwind-exception.cpp @@ -3,6 +3,8 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions %s -O2 -o - | FileCheck %s --check-prefix=ARM-DARWIN // RUN: %clang_cc1 -triple arm-unknown-gnueabi -emit-llvm -fcxx-exceptions -fexceptions %s -O2 -o - | FileCheck %s --check-prefix=ARM-EABI // RUN: %clang_cc1 -triple mipsel-unknown-unknown -emit-llvm -fcxx-exceptions -fexceptions %s -O2 -o - | FileCheck %s --check-prefix=MIPS +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -fcxx-exceptions -fexceptions -exception-model=seh %s -O2 -o - | FileCheck %s --check-prefix=MINGW-X86-64 +// RUN: %clang_cc1 -triple thumbv7-windows-gnu -emit-llvm -fcxx-exceptions -fexceptions -exception-model=seh %s -O2 -o - | FileCheck %s --check-prefix=MINGW-ARMV7 void foo(); void test() { @@ -25,9 +27,15 @@ void test() { // ARM-EABI-NEXT: [[T1:%.*]] = getelementptr i8, ptr [[EXN]], i32 88 // MIPS: [[T0:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXN:%.*]]) [[NUW:#[0-9]+]] // MIPS-NEXT: [[T1:%.*]] = getelementptr i8, ptr [[EXN]], i32 24 +// MINGW-X86-64: [[T0:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXN:%.*]]) [[NUW:#[0-9]+]] +// MINGW-X86-64-NEXT:[[T1:%.*]] = getelementptr i8, ptr [[EXN]], i64 64 +// MINGW-ARMV7: [[T0:%.*]] = tail call arm_aapcs_vfpcc ptr @__cxa_begin_catch(ptr [[EXN:%.*]]) [[NUW:#[0-9]+]] +// MINGW-ARMV7-NEXT: [[T1:%.*]] = getelementptr i8, ptr [[EXN]], i32 48 // X86-64: attributes [[NUW]] = { nounwind } // X86-32: attributes [[NUW]] = { nounwind } // ARM-DARWIN: attributes [[NUW]] = { nounwind } // ARM-EABI: attributes [[NUW]] = { nounwind } // MIPS: attributes [[NUW]] = { nounwind } +// MINGW-X86-64: attributes [[NUW]] = { nounwind } +// MINGW-ARMV7: attributes [[NUW]] = { nounwind } diff --git a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp index 249586f5991f1..b24ece1598327 100644 --- a/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp +++ b/clang/test/CodeGenCXX/vtable-debug-info-inheritance-simple.cpp @@ -1,5 +1,3 @@ -// REQUIRES: target={{x86_64.*-linux.*}} - // Simple inheritance case: // For CBase and CDerived we check: // - Generation of their vtables (including attributes). @@ -30,13 +28,20 @@ int main() { return 0; } -// RUN: %clang --target=x86_64-linux -Xclang -disable-O0-optnone -Xclang -disable-llvm-passes -emit-llvm -S -g %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -mrelocation-model pic -pic-is-pie -debug-info-kind=limited -dwarf-version=5 -disable-O0-optnone -disable-llvm-passes %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -mrelocation-model pic -pic-is-pie -debug-info-kind=limited -dwarf-version=5 -disable-O0-optnone -disable-llvm-passes %s -o - | FileCheck %s --check-prefix=COFF // CHECK: $_ZTVN3NSP5CBaseE = comdat any // CHECK: $_ZTV8CDerived = comdat any // CHECK: @_ZTVN3NSP5CBaseE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[BASE_VTABLE_VAR:![0-9]*]] // CHECK: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8, !dbg [[DERIVED_VTABLE_VAR:![0-9]*]] +// COFF: @_ZTVN3NSP5CBaseE = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8 +// COFF-NOT: !dbg +// COFF-SAME: {{$}} +// COFF: @_ZTV8CDerived = linkonce_odr {{dso_local|hidden}} unnamed_addr constant {{.*}}, comdat, align 8 +// COFF-NOT: !dbg +// COFF-SAME: {{$}} // CHECK: [[BASE_VTABLE_VAR]] = !DIGlobalVariableExpression(var: [[BASE_VTABLE:![0-9]*]], expr: !DIExpression()) // CHECK-NEXT: [[BASE_VTABLE]] = distinct !DIGlobalVariable(name: "_vtable$", linkageName: "_ZTVN3NSP5CBaseE" diff --git a/clang/test/CodeGenCoroutines/coro-gro.cpp b/clang/test/CodeGenCoroutines/coro-gro.cpp index b62134317cef2..037fd03349e76 100644 --- a/clang/test/CodeGenCoroutines/coro-gro.cpp +++ b/clang/test/CodeGenCoroutines/coro-gro.cpp @@ -106,4 +106,31 @@ invoker g() { // CHECK: call void @_ZN7invoker15invoker_promise17get_return_objectEv({{.*}} %[[AggRes]] co_return; } -// CHECK: ![[OutFrameMetadata]] = !{} \ No newline at end of file + +namespace gh148953 { + +struct Task { + struct promise_type { + Task get_return_object(); + std::suspend_always initial_suspend() { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + void return_void() {} + void unhandled_exception() {} + }; + Task() {} + // Different from `invoker`, this Task is copy constructible. + Task(const Task&) {}; +}; + +// NRVO on const qualified return type should work. +// CHECK: define{{.*}} void @_ZN8gh1489537exampleEv({{.*}} sret(%"struct.gh148953::Task") align 1 %[[NrvoRes:.+]]) +const Task example() { + // CHECK: %[[ResultPtr:.+]] = alloca ptr + // CHECK: store ptr %[[NrvoRes]], ptr %[[ResultPtr]] + // CHECK: coro.init: + // CHECK: call void @_ZN8gh1489534Task12promise_type17get_return_objectEv({{.*}} %[[NrvoRes:.+]], {{.*}}) + co_return; +} + +} // namespace gh148953 +// CHECK: ![[OutFrameMetadata]] = !{} diff --git a/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m new file mode 100644 index 0000000000000..b51670fd6459a --- /dev/null +++ b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -fptrauth-block-descriptor-pointers -triple arm64e-apple-ios -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -triple arm64e-apple-ios -DNO_BLOCK_DESC_AUTH -emit-llvm -o - %s | FileCheck %s --check-prefix=NODESCRIPTORAUTH + +#ifndef NO_BLOCK_DESC_AUTH +_Static_assert(__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should set ptrauth_signed_block_descriptors"); +#else +_Static_assert(!__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should not be enabled by default"); +#endif + +void a() { + // Test out a global block. + void (^blk)(void) = ^{}; +} + +// CHECK: [[BLOCK_DESCRIPTOR_NAME:@"__block_descriptor_.*"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, ptr, ptr } { i64 0, i64 32, ptr @.str, ptr null } +// CHECK: @__block_literal_global = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 1342177280, i32 0, ptr ptrauth (ptr @__a_block_invoke, i32 0, i64 0, ptr getelementptr inbounds ({ ptr, i32, i32, ptr, ptr }, ptr @__block_literal_global, i32 0, i32 3)), ptr ptrauth (ptr [[BLOCK_DESCRIPTOR_NAME]], i32 2, i64 49339, ptr getelementptr inbounds ({ ptr, i32, i32, ptr, ptr }, ptr @__block_literal_global, i32 0, i32 4)) } + +// NODESCRIPTORAUTH: [[BLOCK_DESCRIPTOR_NAME:@"__block_descriptor_.*"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, ptr, ptr } { i64 0, i64 32, ptr @.str, ptr null } +// NODESCRIPTORAUTH: @__block_literal_global = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 1342177280, i32 0, ptr ptrauth (ptr @__a_block_invoke, i32 0, i64 0, ptr getelementptr inbounds ({ ptr, i32, i32, ptr, ptr }, ptr @__block_literal_global, i32 0, i32 3)), ptr [[BLOCK_DESCRIPTOR_NAME]] } + + +void b(int p) { + // CHECK-LABEL: define void @b + + // Test out a stack block. + void (^blk)(void) = ^{(void)p;}; + + // CHECK: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, i32 }> + // CHECK: [[BLOCK_DESCRIPTOR_REF:%.*]] = getelementptr inbounds nuw <{ {{.*}} }>, ptr [[BLOCK]], i32 0, i32 4 + // CHECK: [[BLOCK_DESCRIPTOR_REF_INT:%.*]] = ptrtoint ptr [[BLOCK_DESCRIPTOR_REF]] to i64 + // CHECK: [[BLENDED:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[BLOCK_DESCRIPTOR_REF_INT]], i64 49339) + // CHECK: [[SIGNED_REF:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @"__block_descriptor_36_e5_v8\01?0l" to i64), i32 2, i64 [[BLENDED]]) + // CHECK: [[SIGNED_REF_PTR:%.*]] = inttoptr i64 [[SIGNED_REF]] to ptr + // CHECK: store ptr [[SIGNED_REF_PTR]], ptr [[BLOCK_DESCRIPTOR_REF]] + + // NODESCRIPTORAUTH: [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, i32 }> + // NODESCRIPTORAUTH: [[BLOCK_DESCRIPTOR_REF:%.*]] = getelementptr inbounds nuw <{ {{.*}} }>, ptr [[BLOCK]], i32 0, i32 4 + // NODESCRIPTORAUTH: store ptr @"__block_descriptor_36_e5_v8\01?0l", ptr [[BLOCK_DESCRIPTOR_REF]] +} diff --git a/clang/test/CodeGenObjC/ptrauth-block-isa.m b/clang/test/CodeGenObjC/ptrauth-block-isa.m index c1e98c6fd9d3e..248e57769ba1e 100644 --- a/clang/test/CodeGenObjC/ptrauth-block-isa.m +++ b/clang/test/CodeGenObjC/ptrauth-block-isa.m @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 -fptrauth-calls -fptrauth-objc-isa -fobjc-arc -fblocks -triple arm64e -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fptrauth-calls -fptrauth-objc-isa -fobjc-arc -fblocks -triple arm64e -emit-llvm %s -o - | FileCheck %s void (^globalblock)(void) = ^{}; -// CHECK: [[GLOBAL_BLOCK:@.*]] = internal constant { ptr, i32, i32, ptr, ptr } { ptr ptrauth (ptr @_NSConcreteGlobalBlock, i32 2, i64 27361, ptr [[GLOBAL_BLOCK]]), i32 1342177280, i32 0, ptr @globalblock_block_invoke, ptr @"__block_descriptor_32_e5_v8\01?0l" }, align 8 #0 +// CHECK: [[BLOCK_DESCRIPTOR_NAME:@"__block_descriptor_.*"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, ptr, ptr } { i64 0, i64 32, ptr @.str, ptr null }, comdat, align 8 +// CHECK: @__block_literal_global = internal constant { ptr, i32, i32, ptr, ptr } { ptr ptrauth (ptr @_NSConcreteGlobalBlock, i32 2, i64 27361, ptr @__block_literal_global), i32 1342177280, i32 0, ptr ptrauth (ptr @globalblock_block_invoke, i32 0, i64 0, ptr getelementptr inbounds ({ ptr, i32, i32, ptr, ptr }, ptr @__block_literal_global, i32 0, i32 3)), ptr [[BLOCK_DESCRIPTOR_NAME]] } @interface A - (int) count; diff --git a/clang/test/DebugInfo/KeyInstructions/asm.c b/clang/test/DebugInfo/KeyInstructions/asm.c new file mode 100644 index 0000000000000..2b3301660f7ba --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/asm.c @@ -0,0 +1,59 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -O0 -emit-llvm -x c %s -o - -gkey-instructions -debug-info-kind=line-tables-only -gno-column-info | FileCheck %s +// Partially copied from clang/test/CodeGen/AArch64/ls64-inline-asm.c + +// Check the inline asm call and result store are Key and distinct atoms. + +struct foo { unsigned long long x[8]; }; +// CHECK-LABEL: define dso_local void @load( +// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG5:![0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG9:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG9]] +// CHECK-NEXT: [[TMP2:%.*]] = call i512 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1:[0-9]+]], !dbg [[DBG10:![0-9]+]], !srcloc [[META11:![0-9]+]] +// CHECK-NEXT: store i512 [[TMP2]], ptr [[TMP0]], align 8, !dbg [[DBG12:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG13:![0-9]+]] +// +void load(struct foo *output, void *addr) { + __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory"); +} + +// CHECK-LABEL: define dso_local void @load2( +// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0]] !dbg [[DBG14:![0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8 +// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG15:![0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG15]] +// CHECK-NEXT: [[TMP2:%.*]] = call i32 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1]], !dbg [[DBG16:![0-9]+]], !srcloc [[META17:![0-9]+]] +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP0]], align 4, !dbg [[DBG18:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG19:![0-9]+]] +// +void load2(int *output, void *addr) { + __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory"); +} +//. +// CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None) +// CHECK: [[META1]] = !DIFile(filename: "{{.*}}", directory: {{.*}}) +// CHECK: [[DBG5]] = distinct !DISubprogram(name: "load", scope: [[META6:![0-9]+]], file: [[META6]], line: 21, type: [[META7:![0-9]+]], scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true) +// CHECK: [[META6]] = !DIFile(filename: "{{.*}}asm.c", directory: {{.*}}) +// CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]]) +// CHECK: [[META8]] = !{} +// CHECK: [[DBG9]] = !DILocation(line: 22, scope: [[DBG5]]) +// CHECK: [[DBG10]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 1, atomRank: 1) +// CHECK: [[META11]] = !{i64 1458} +// CHECK: [[DBG12]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 2, atomRank: 1) +// CHECK: [[DBG13]] = !DILocation(line: 23, scope: [[DBG5]], atomGroup: 3, atomRank: 1) +// CHECK: [[DBG14]] = distinct !DISubprogram(name: "load2", scope: [[META6]], file: [[META6]], line: 38, type: [[META7]], scopeLine: 38, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true) +// CHECK: [[DBG15]] = !DILocation(line: 39, scope: [[DBG14]]) +// CHECK: [[DBG16]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 1, atomRank: 1) +// CHECK: [[META17]] = !{i64 2501} +// CHECK: [[DBG18]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 2, atomRank: 1) +// CHECK: [[DBG19]] = !DILocation(line: 40, scope: [[DBG14]], atomGroup: 3, atomRank: 1) +//. diff --git a/clang/test/DebugInfo/KeyInstructions/goto.c b/clang/test/DebugInfo/KeyInstructions/goto.c new file mode 100644 index 0000000000000..ead92e600ca5b --- /dev/null +++ b/clang/test/DebugInfo/KeyInstructions/goto.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ -std=c++17 %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \ +// RUN: | FileCheck %s + +// Check the goto branches get Key Instructions metadata. +void ext(); +void test_goto(void) { +// CHECK: br label %dst1, !dbg [[G1R1:!.*]] + goto dst1; +dst1: + ext(); + + void *ptr = &&dst2; +// CHECK: br label %indirectgoto, !dbg [[G3R1:!.*]] + goto *ptr; +dst2: + ext(); + +// CHECK: br label %dst3, !dbg [[G4R1:!.*]] + goto *&&dst3; +dst3: + ext(); + + return; +} + +// CHECK: [[G1R1]] = !DILocation(line: 10, scope: ![[#]], atomGroup: 1, atomRank: 1) +// CHECK: [[G3R1]] = !DILocation(line: 16, scope: ![[#]], atomGroup: 3, atomRank: 1) +// CHECK: [[G4R1]] = !DILocation(line: 21, scope: ![[#]], atomGroup: 4, atomRank: 1) diff --git a/clang/test/Driver/DTLTO/dtlto.c b/clang/test/Driver/DTLTO/dtlto.c new file mode 100644 index 0000000000000..96795d9a4e6a4 --- /dev/null +++ b/clang/test/Driver/DTLTO/dtlto.c @@ -0,0 +1,48 @@ +// REQUIRES: lld + +/// Check DTLTO options are forwarded to the linker. + +/// Check that options are forwarded as expected with --thinlto-distributor=. +// RUN: %clang -flto=thin %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ +// RUN: -Xthinlto-distributor=a1 -Xthinlto-distributor=a2,a3 \ +// RUN: -fthinlto-distributor=d.exe -Werror 2>&1 | \ +// RUN: FileCheck %s --check-prefix=FORWARD + +// FORWARD: ld.lld +// FORWARD-SAME: "--thinlto-distributor=d.exe" +// FORWARD-SAME: "--thinlto-remote-compiler={{[^"]+}}" +// FORWARD-SAME: "--thinlto-distributor-arg=a1" +// FORWARD-SAME: "--thinlto-distributor-arg=a2" +// FORWARD-SAME: "--thinlto-distributor-arg=a3" + +/// Check that options are not added without --thinlto-distributor= and +/// that a warning is issued for unused -Xthinlto-distributor options. +// RUN: %clang -flto=thin %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ +// RUN: -Xthinlto-distributor=a1 -Xthinlto-distributor=a2,a3 2>&1 | \ +// RUN: FileCheck %s --check-prefix=NODIST --implicit-check-not=distributor \ +// RUN: --implicit-check-not=remote-compiler + +// NODIST: warning: argument unused during compilation: '-Xthinlto-distributor=a1' +// NODIST: warning: argument unused during compilation: '-Xthinlto-distributor=a2,a3' +// NODIST: ld.lld + +/// Check the expected arguments are forwarded by default with only +/// --thinlto-distributor=. +// RUN: %clang -flto=thin %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ +// RUN: -fthinlto-distributor=d.exe -Werror 2>&1 | \ +// RUN: FileCheck %s --check-prefix=DEFAULT --implicit-check-not=distributor \ +// RUN: --implicit-check-not=remote-compiler + +// DEFAULT: ld.lld +// DEFAULT-SAME: "--thinlto-distributor=d.exe" +// DEFAULT-SAME: "--thinlto-remote-compiler={{.*}}clang{{[^\"]*}}" + +/// Check that nothing is forwarded when the compiler is not in LTO mode, and that +/// appropriate unused option warnings are issued. +// RUN: %clang %s -### -fuse-ld=lld --target=x86_64-linux-gnu \ +// RUN: -fthinlto-distributor=d.exe 2>&1 | \ +// RUN: FileCheck %s --check-prefix=NOFLTO --implicit-check-not=distributor \ +// RUN: --implicit-check-not=remote-compiler + +// NOFLTO: warning: argument unused during compilation: '-fthinlto-distributor=d.exe' +// NOFLTO: ld.lld diff --git a/clang/test/Driver/aarch64-toolchain.c b/clang/test/Driver/aarch64-toolchain.c index cfad4b8eb6829..512b5a883cd5b 100644 --- a/clang/test/Driver/aarch64-toolchain.c +++ b/clang/test/Driver/aarch64-toolchain.c @@ -11,7 +11,7 @@ // LLD-AARCH64-BAREMETAL: "-isysroot" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf" // LLD-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include" // LLD-AARCH64-BAREMETAL: "{{.*}}/Inputs/lld/ld.lld" -// LLD-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64linux" "-EL" +// LLD-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64elf" "-EL" // LLD-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/lib/crt0.o" // LLD-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // LLD-AARCH64-BAREMETAL: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -30,7 +30,7 @@ // C-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include" // C-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" // C-AARCH64-BAREMETAL: "--sysroot={{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf" -// C-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64linux" "-EL" +// C-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64elf" "-EL" // C-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/lib/crt0.o" // C-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // C-AARCH64-BAREMETAL: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -47,7 +47,7 @@ // C-AARCH64-BAREMETAL-NOSYSROOT: "-cc1" "-triple" "aarch64-unknown-none-elf" // C-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include" // C-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" -// C-AARCH64-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "aarch64linux" "-EL" +// C-AARCH64-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "aarch64elf" "-EL" // C-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/lib/crt0.o" // C-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // C-AARCH64-BAREMETAL-NOSYSROOT: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -67,7 +67,7 @@ // CXX-AARCH64-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include" // CXX-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" // CXX-AARCH64-BAREMETAL: "--sysroot={{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf" -// CXX-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64linux" "-EL" +// CXX-AARCH64-BAREMETAL: "-Bstatic" "-m" "aarch64elf" "-EL" // CXX-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/lib/crt0.o" // CXX-AARCH64-BAREMETAL: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // CXX-AARCH64-BAREMETAL: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -86,7 +86,7 @@ // CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/8.2.1" // CXX-AARCH64-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include" // CXX-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" -// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "aarch64linux" "-EL" +// CXX-AARCH64-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "aarch64elf" "-EL" // CXX-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/lib/crt0.o" // CXX-AARCH64-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // CXX-AARCH64-BAREMETAL-NOSYSROOT: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -105,7 +105,7 @@ // CXX-AARCH64-BAREMETAL-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/include" // CXX-AARCH64-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" // CXX-AARCH64-BAREMETAL-LIBCXX: "--sysroot={{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf" -// CXX-AARCH64-BAREMETAL-LIBCXX: "-Bstatic" "-m" "aarch64linux" "-EL" +// CXX-AARCH64-BAREMETAL-LIBCXX: "-Bstatic" "-m" "aarch64elf" "-EL" // CXX-AARCH64-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/aarch64-none-elf/lib/crt0.o" // CXX-AARCH64-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // CXX-AARCH64-BAREMETAL-LIBCXX: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" @@ -122,7 +122,7 @@ // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include/c++/v1" // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/include" // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../bin/aarch64-none-elf-ld" -// CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-Bstatic" "-m" "aarch64linux" "-EL" +// CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-Bstatic" "-m" "aarch64elf" "-EL" // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/../../../../aarch64-none-elf/lib/crt0.o" // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1/crtbegin.o" // CXX-AARCH64-BAREMETAL-NOSYSROOT-LIBCXX: "-L{{.*}}/Inputs/basic_aarch64_gcc_tree/lib/gcc/aarch64-none-elf/8.2.1" diff --git a/clang/test/Driver/aarch64-v96a.c b/clang/test/Driver/aarch64-v96a.c index de7890140ebd3..e0081bbbdabfe 100644 --- a/clang/test/Driver/aarch64-v96a.c +++ b/clang/test/Driver/aarch64-v96a.c @@ -6,7 +6,7 @@ // RUN: %clang -target aarch64 -mlittle-endian -march=armv9.6-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.6-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A %s -// GENERICV96A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+cmpbr"{{.*}} "-target-feature" "+fprcvt"{{.*}} "-target-feature" "+sve2p2" +// GENERICV96A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+cmpbr"{{.*}} // RUN: %clang -target aarch64_be -march=armv9.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A-BE %s // RUN: %clang -target aarch64_be -march=armv9.6-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A-BE %s @@ -14,7 +14,7 @@ // RUN: %clang -target aarch64 -mbig-endian -march=armv9.6-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.6-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV96A-BE %s -// GENERICV96A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+cmpbr"{{.*}} "-target-feature" "+fprcvt"{{.*}} "-target-feature" "+sve2p2" +// GENERICV96A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+cmpbr"{{.*}} // ===== Features supported on aarch64 ===== diff --git a/clang/test/Driver/arch-arm64e.c b/clang/test/Driver/arch-arm64e.c index 0fb12d4dcc5e3..39006d203989b 100644 --- a/clang/test/Driver/arch-arm64e.c +++ b/clang/test/Driver/arch-arm64e.c @@ -2,11 +2,20 @@ // RUN: %clang -target arm64-apple-darwin -c %s -### 2>&1 | FileCheck %s --check-prefix NONE // NONE: "-cc1" -// NONE-NOT: "-fptrauth-intrinsics" + // NONE-NOT: "-fptrauth-calls" // NONE-NOT: "-fptrauth-returns" +// NONE-NOT: "-fptrauth-intrinsics" // NONE-NOT: "-fptrauth-indirect-gotos" // NONE-NOT: "-fptrauth-auth-traps" +// NONE-NOT: "-fptrauth-vtable-pointer-address-discrimination" +// NONE-NOT: "-fptrauth-vtable-pointer-type-discrimination" +// NONE-NOT: "-fptrauth-objc-isa" +// NONE-NOT: "-fptrauth-objc-class-ro" +// NONE-NOT: "-fptrauth-objc-interface-sel" + +// Final catch all if any new flags are added +// NONE-NOT: "-fptrauth" // RUN: %clang -target arm64-apple-darwin -fptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix CALL // CALL: "-cc1"{{.*}} {{.*}} "-fptrauth-calls" @@ -23,39 +32,39 @@ // RUN: %clang -target arm64-apple-darwin -fptrauth-auth-traps -c %s -### 2>&1 | FileCheck %s --check-prefix TRAPS // TRAPS: "-cc1"{{.*}} {{.*}} "-fptrauth-auth-traps" - // Check the arm64e defaults. // RUN: %clang -target arm64e-apple-ios -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT +// RUN: %clang -target arm64e-apple-macos -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULTMAC +// RUN: %if system-darwin && target={{.*}}-{{darwin|macos}}{{.*}} %{ %clang -target arm64e-apple-macos -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULTARCH %} // RUN: %clang -mkernel -target arm64e-apple-ios -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT // RUN: %clang -fapple-kext -target arm64e-apple-ios -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT -// DEFAULT: "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" {{.*}}"-target-cpu" "apple-a12"{{.*}} +// DEFAULT: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12"{{.*}} +// DEFAULTMAC: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-m1"{{.*}} +// DEFAULTARCH: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" // RUN: %clang -target arm64e-apple-none-macho -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT-MACHO -// DEFAULT-MACHO: "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" {{.*}}"-target-cpu" "apple-a12"{{.*}} +// DEFAULT-MACHO: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12"{{.*}} // RUN: %clang -target arm64e-apple-ios -fno-ptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT-NOCALL -// RUN: %clang -mkernel -target arm64e-apple-ios -fno-ptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT-NOCALL -// RUN: %clang -fapple-kext -target arm64e-apple-ios -fno-ptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix DEFAULT-NOCALL // DEFAULT-NOCALL-NOT: "-fptrauth-calls" -// DEFAULT-NOCALL: "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" {{.*}}"-target-cpu" "apple-a12" +// DEFAULT-NOCALL: "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12" // RUN: %clang -target arm64e-apple-ios -fno-ptrauth-returns -c %s -### 2>&1 | FileCheck %s --check-prefix NORET // NORET-NOT: "-fptrauth-returns" -// NORET: "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" {{.*}}"-target-cpu" "apple-a12" +// NORET: "-fptrauth-calls" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12" // RUN: %clang -target arm64e-apple-ios -fno-ptrauth-intrinsics -c %s -### 2>&1 | FileCheck %s --check-prefix NOINTRIN -// NOINTRIN: "-fptrauth-returns" // NOINTRIN-NOT: "-fptrauth-intrinsics" -// NOINTRIN: "-fptrauth-calls" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" {{.*}}"-target-cpu" "apple-a12"{{.*}} +// NOINTRIN: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-indirect-gotos" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12" // RUN: %clang -target arm64e-apple-ios -fno-ptrauth-auth-traps -c %s -### 2>&1 | FileCheck %s --check-prefix NOTRAP -// NOTRAP: "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-indirect-gotos" {{.*}}"-target-cpu" "apple-a12" +// NOTRAP: "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-intrinsics" "-fptrauth-indirect-gotos" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-objc-isa" "-fptrauth-objc-class-ro" "-fptrauth-objc-interface-sel" {{.*}}"-target-cpu" "apple-a12" // Check the CPU defaults and overrides. diff --git a/clang/test/Driver/arm-toolchain.c b/clang/test/Driver/arm-toolchain.c index c367594b0a758..9005992f2b759 100644 --- a/clang/test/Driver/arm-toolchain.c +++ b/clang/test/Driver/arm-toolchain.c @@ -10,7 +10,7 @@ // LLD-ARM-BAREMETAL: "-isysroot" "{{.*}}Inputs/basic_arm_gcc_tree/armv6m-none-eabi" // LLD-ARM-BAREMETAL: "-internal-isystem" "{{.*}}Inputs/basic_arm_gcc_tree/armv6m-none-eabi/include" // LLD-ARM-BAREMETAL: "{{.*}}/Inputs/lld/ld.lld" -// LLD-ARM-BAREMETAL: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// LLD-ARM-BAREMETAL: "-Bstatic" "-m" "armelf" "-EL" // LLD-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/lib/crt0.o" // LLD-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // LLD-ARM-BAREMETAL: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -29,7 +29,7 @@ // C-ARM-BAREMETAL: "-internal-isystem" "{{.*}}Inputs/basic_arm_gcc_tree/armv6m-none-eabi/include" // C-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" // C-ARM-BAREMETAL: "--sysroot={{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi" -// C-ARM-BAREMETAL: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// C-ARM-BAREMETAL: "-Bstatic" "-m" "armelf" "-EL" // C-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/lib/crt0.o" // C-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // C-ARM-BAREMETAL: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -46,7 +46,7 @@ // C-ARM-BAREMETAL-NOSYSROOT: "-cc1" "-triple" "thumbv6m-unknown-none-eabi" // C-ARM-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/include" // C-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" -// C-ARM-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// C-ARM-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "armelf" "-EL" // C-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/lib/crt0.o" // C-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // C-ARM-BAREMETAL-NOSYSROOT: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -67,7 +67,7 @@ // CXX-ARM-BAREMETAL: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/include" // CXX-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" // CXX-ARM-BAREMETAL: "--sysroot={{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi" -// CXX-ARM-BAREMETAL: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CXX-ARM-BAREMETAL: "-Bstatic" "-m" "armelf" "-EL" // CXX-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/lib/crt0.o" // CXX-ARM-BAREMETAL: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // CXX-ARM-BAREMETAL: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -87,7 +87,7 @@ // CXX-ARM-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/include/c++/8.2.1" // CXX-ARM-BAREMETAL-NOSYSROOT: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/include" // CXX-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" -// CXX-ARM-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CXX-ARM-BAREMETAL-NOSYSROOT: "-Bstatic" "-m" "armelf" "-EL" // CXX-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/lib/crt0.o" // CXX-ARM-BAREMETAL-NOSYSROOT: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // CXX-ARM-BAREMETAL-NOSYSROOT: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -106,7 +106,7 @@ // CXX-ARM-BAREMETAL-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/include" // CXX-ARM-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" // CXX-ARM-BAREMETAL-LIBCXX: "--sysroot={{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi" -// CXX-ARM-BAREMETAL-LIBCXX: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CXX-ARM-BAREMETAL-LIBCXX: "-Bstatic" "-m" "armelf" "-EL" // CXX-ARM-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/armv6m-none-eabi/lib/crt0.o" // CXX-ARM-BAREMETAL-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // CXX-ARM-BAREMETAL-LIBCXX: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" @@ -123,7 +123,7 @@ // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/include/c++/v1" // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "-internal-isystem" "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/include" // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../bin/armv6m-none-eabi-ld" -// CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "-Bstatic" "-m" "armelf" "-EL" // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/../../../../armv6m-none-eabi/lib/crt0.o" // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1/crtbegin.o" // CXX-ARM-BAREMETAL-NOSYSROOT-LIBCXX: "-L{{.*}}/Inputs/basic_arm_gcc_tree/lib/gcc/armv6m-none-eabi/8.2.1" diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp index 4dc320191317e..8b5ab4355087b 100644 --- a/clang/test/Driver/baremetal.cpp +++ b/clang/test/Driver/baremetal.cpp @@ -17,7 +17,7 @@ // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp" // CHECK-V6M-C-NEXT: ld{{(.exe)?}}" // CHECK-V6M-C-SAME: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-V6M-C-SAME: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-C-SAME: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-C-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for" // CHECK-V6M-C-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" @@ -43,7 +43,7 @@ // CHECK-V6M-TREE-SAME: "-internal-isystem" "[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}armv6m-unknown-none-eabi" // CHECK-V6M-TREE-SAME: "-x" "c++" "{{.*}}baremetal.cpp" // CHECK-V6M-TREE-NEXT: ld{{(.exe)?}}" -// CHECK-V6M-TREE-SAME: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-TREE-SAME: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-TREE-SAME: "[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi{{[/\\]+}}crt0.o" // CHECK-V6M-TREE-SAME: "-L[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi" // CHECK-V6M-TREE-SAME "{{.*}}.o" @@ -60,7 +60,7 @@ // CHECK-ARMV7M-PER-TARGET: "-x" "c++" "{{.*}}baremetal.cpp" // CHECK-ARMV7M-PER-TARGET: ld{{(.exe)?}}" // CHECK-ARMV7M-PER-TARGET: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-ARMV7M-PER-TARGET: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-ARMV7M-PER-TARGET: "-Bstatic" "-m" "armelf" "-EL" // CHECK-ARMV7M-PER_TARGET: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-ARMV7M-PER-TARGET: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib" // CHECK-ARMV7M-PER-TARGET: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}armv7m-vendor-none-eabi @@ -73,7 +73,7 @@ // CHECK-V6M-DEFAULTCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-V6M-DEFAULTCXX: ld{{(.exe)?}}" // CHECK-V6M-DEFAULTCXX: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-V6M-DEFAULTCXX: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-DEFAULTCXX: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-DEFAULTCXX-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o" // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-DEFAULTCXX-SAME: "{{.*}}.o" @@ -90,7 +90,7 @@ // CHECK-V6M-LIBCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1" // CHECK-V6M-LIBCXX: ld{{(.exe)?}}" // CHECK-V6M-LIBCXX-SAME: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-V6M-LIBCXX-SAME: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-LIBCXX-SAME: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-LIBCXX-SAME: "{{.*}}.o" // CHECK-V6M-LIBCXX-SAME: "-lc++" @@ -108,7 +108,7 @@ // CHECK-V6M-LIBSTDCXX-SAME: "-internal-isystem" "{{[^"]+}}{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}6.0.0" // CHECK-V6M-LIBSTDCXX: ld{{(.exe)?}}" // CHECK-V6M-LIBSTDCXX-SAME: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-V6M-LIBSTDCXX-SAME: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-LIBSTDCXX-SAME: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // CHECK-V6M-LIBSTDCXX-SAME: "{{.*}}.o" // CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lm" @@ -123,7 +123,7 @@ // CHECK-V6M-NDL: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-V6M-NDL: ld{{(.exe)?}}" // CHECK-V6M-NDL: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-V6M-NDL: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-V6M-NDL: "-Bstatic" "-m" "armelf" "-EL" // CHECK-V6M-NDL-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib" // RUN: rm -rf %T/baremetal_cxx_sysroot @@ -171,7 +171,7 @@ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // CHECK-ARMV7EB: "{{.*}}ld{{(.exe)?}}" // CHECK-ARMV7EB: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-ARMV7EB: "-Bstatic" "-m" "armelfb_linux_eabi" "--be8" "-EB" +// CHECK-ARMV7EB: "-Bstatic" "-m" "armelfb" "--be8" "-EB" // RUN: %clang -### %s --target=armv7-none-eabi -mbig-endian --sysroot=%S/Inputs/baremetal_arm 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s @@ -183,7 +183,7 @@ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // CHECK-ARMV7EL: "{{.*}}ld{{(.exe)?}}" // CHECK-ARMV7EL: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-ARMV7EL: "-Bstatic" "-m" "armelf_linux_eabi" "-EL" +// CHECK-ARMV7EL: "-Bstatic" "-m" "armelf" "-EL" // CHECK-ARMV7EL-NOT: "--be8" // RUN: %clang -### %s --target=armebv7-none-eabi -mlittle-endian --sysroot=%S/Inputs/baremetal_arm 2>&1 \ @@ -196,7 +196,7 @@ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // CHECK-AARCH64BE: "{{.*}}ld{{(.exe)?}}" // CHECK-AARCH64BE: sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-AARCH64BE: "-Bstatic" "-m" "aarch64linuxb" "-EB" +// CHECK-AARCH64BE: "-Bstatic" "-m" "aarch64elfb" "-EB" // CHECK-AARCH64BE-NOT: "--be8" // RUN: %clang -### %s --target=aarch64-none-elf -mbig-endian --sysroot=%S/Inputs/baremetal_arm 2>&1 \ @@ -209,7 +209,7 @@ // RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s // CHECK-AARCH64LE: "{{.*}}ld{{(.exe)?}}" // CHECK-AARCH64LE: "--sysroot={{.*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm" -// CHECK-AARCH64LE: "-Bstatic" "-m" "aarch64linux" "-EL" +// CHECK-AARCH64LE: "-Bstatic" "-m" "aarch64elf" "-EL" // CHECK-AARCH64LE-NOT: "--be8" // RUN: %clang -### %s --target=aarch64_be-none-elf -mlittle-endian --sysroot=%S/Inputs/baremetal_arm 2>&1 \ @@ -257,7 +257,7 @@ // CHECK-RV64-SAME:"{{.*}}.o" // CHECK-RV64-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-SAME: "-lc" -// CHECK-RV64-SAME: "-X" "-o" "{{.*}}.tmp.out" +// CHECK-RV64-SAME: "-o" "{{.*}}.tmp.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -271,7 +271,7 @@ // CHECK-RV64-DEFAULTCXX-SAME: "-lc++" "-lm" // CHECK-RV64-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-DEFAULTCXX-SAME: "-lc" -// CHECK-RV64-DEFAULTCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-DEFAULTCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -288,7 +288,7 @@ // CHECK-RV64-LIBCXX-SAME: "-lc++" "-lm" // CHECK-RV64-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-LIBCXX-SAME: "-lc" -// CHECK-RV64-LIBCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-LIBCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \ @@ -305,7 +305,7 @@ // CHECK-RV64-LIBSTDCXX-SAME: "-lstdc++" "-lm" // CHECK-RV64-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV64-LIBSTDCXX-SAME: "-lc" -// CHECK-RV64-LIBSTDCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV64-LIBSTDCXX-SAME: "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: -L some/directory/user/asked/for \ @@ -325,7 +325,7 @@ // CHECK-RV32-SAME: "{{.*}}.o" // CHECK-RV32-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-SAME: "-lc" -// CHECK-RV32-SAME: "-X" "-o" "a.out" +// CHECK-RV32-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -339,7 +339,7 @@ // CHECK-RV32-DEFAULTCXX-SAME: "-lc++" "-lm" // CHECK-RV32-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-DEFAULTCXX-SAME: "-lc" -// CHECK-RV32-DEFAULTCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-DEFAULTCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -355,7 +355,7 @@ // CHECK-RV32-LIBCXX-SAME: "{{.*}}.o" // CHECK-RV32-LIBCXX-SAME: "-lc++" "-lm" // CHECK-RV32-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" -// CHECK-RV32-LIBCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-LIBCXX-SAME: "-o" "a.out" // RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \ // RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \ @@ -372,7 +372,7 @@ // CHECK-RV32-LIBSTDCXX-SAME: "-lstdc++" "-lm" // CHECK-RV32-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a" // CHECK-RV32-LIBSTDCXX-SAME: "-lc" -// CHECK-RV32-LIBSTDCXX-SAME: "-X" "-o" "a.out" +// CHECK-RV32-LIBSTDCXX-SAME: "-o" "a.out" // RUN: %clang %s -### 2>&1 --target=riscv64-unknown-elf \ // RUN: -nostdlibinc -nobuiltininc \ diff --git a/clang/test/Driver/mingw-msvcrt.c b/clang/test/Driver/mingw-msvcrt.c index 340ce1f57b0f8..e1648630476a0 100644 --- a/clang/test/Driver/mingw-msvcrt.c +++ b/clang/test/Driver/mingw-msvcrt.c @@ -7,10 +7,10 @@ // CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32" // CHECK_DEFAULT-SAME: "-lmsvcrt" "-lkernel32" "{{.*}}crtend.o" // CHECK_MSVCR120: "-lmsvcr120" -// CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32" +// CHECK_MSVCR120-SAME: "-lmingwex" "-lmsvcr120" "-ladvapi32" // CHECK_UCRTBASE: "-lucrtbase" -// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRTBASE-SAME: "-lmingwex" "-lucrtbase" "-ladvapi32" // CHECK_UCRT: "-lucrt" -// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRT-SAME: "-lmingwex" "-lucrt" "-ladvapi32" // CHECK_CRTDLL: "-lcrtdll" -// CHECK_CRTDLL-SAME: "-lmingwex" "-ladvapi32" +// CHECK_CRTDLL-SAME: "-lmingwex" "-lcrtdll" "-ladvapi32" diff --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c index 6639e9d2d9d67..1f12cfca9488b 100644 --- a/clang/test/Driver/openbsd.c +++ b/clang/test/Driver/openbsd.c @@ -127,9 +127,12 @@ // UNWIND-TABLES: "-funwind-tables=2" // NO-UNWIND-TABLES-NOT: "-funwind-tables=2" -// Check that the -X and --no-relax flags are passed to the linker on riscv64 +// Check that the -X and --no-relax flags are passed to the linker +// RUN: %clang --target=loongarch64-unknown-openbsd -mno-relax -### %s 2>&1 \ +// RUN: | FileCheck --check-prefix=LA64-FLAGS %s // RUN: %clang --target=riscv64-unknown-openbsd -mno-relax -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=RISCV64-FLAGS %s +// LA64-FLAGS: "-X" "--no-relax" // RISCV64-FLAGS: "-X" "--no-relax" // Check passing LTO flags to the linker diff --git a/clang/test/Driver/sparc-target-features.c b/clang/test/Driver/sparc-target-features.c index a839604ff1bc0..bd17da112bbd2 100644 --- a/clang/test/Driver/sparc-target-features.c +++ b/clang/test/Driver/sparc-target-features.c @@ -20,6 +20,11 @@ // RUN: %clang --target=sparc -mvis2 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s // RUN: %clang --target=sparc -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s +/// Solaris/SPARC defaults to -mvis2 +// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s +// RUN: %clang --target=sparc-sun-solaris2.11 -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s +// RUN: %clang --target=sparcv9-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s +// RUN: %clang --target=sparcv9-sun-solaris2.11 -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s // VIS2: "-target-feature" "+vis2" // NO-VIS2: "-target-feature" "-vis2" @@ -34,4 +39,8 @@ // SOFT-QUAD-FLOAT: "-target-feature" "-hard-quad-float" // RUN: %clang --target=sparc -mv8plus %s -### 2>&1 | FileCheck -check-prefix=V8PLUS %s +/// 32-bit Solaris/SPARC defaults to -mv8plus +// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=V8PLUS %s +// RUN: %clang --target=sparc-sun-solaris2.11 -mno-v8plus %s -### 2>&1 | FileCheck -check-prefix=NO-V8PLUS %s // V8PLUS: "-target-feature" "+v8plus" +// NO-V8PLUS-NOT: "-target-feature" "+v8plus" diff --git a/clang/test/ExtractAPI/typedef.c b/clang/test/ExtractAPI/typedef.c index a4c3619bfd210..6099cd62f8776 100644 --- a/clang/test/ExtractAPI/typedef.c +++ b/clang/test/ExtractAPI/typedef.c @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing -fblocks \ // RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json -verify // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix MYINT @@ -90,4 +90,83 @@ void foo(BarPtr value); void baz(BarPtr *value); // CHECK-NOT: struct Bar * +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BLOCKPTR +typedef int (^CustomType)(const unsigned int *, unsigned long); +void bar(CustomType block); + +// BLOCKPTR-LABEL: "!testLabel": "c:@F@bar", +// BLOCKPTR: "declarationFragments": [ +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "typeIdentifier", +// BLOCKPTR-NEXT: "preciseIdentifier": "c:v", +// BLOCKPTR-NEXT: "spelling": "void" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "text", +// BLOCKPTR-NEXT: "spelling": " " +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "identifier", +// BLOCKPTR-NEXT: "spelling": "bar" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "text", +// BLOCKPTR-NEXT: "spelling": "(" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "typeIdentifier", +// BLOCKPTR-NEXT: "preciseIdentifier": "c:typedef.c@T@CustomType", +// BLOCKPTR-NEXT: "spelling": "CustomType" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "text", +// BLOCKPTR-NEXT: "spelling": " " +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "internalParam", +// BLOCKPTR-NEXT: "spelling": "block" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "text", +// BLOCKPTR-NEXT: "spelling": ");" +// BLOCKPTR-NEXT: } +// BLOCKPTR-NEXT: ], +// BLOCKPTR-NEXT: "functionSignature": { +// BLOCKPTR-NEXT: "parameters": [ +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "declarationFragments": [ +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "typeIdentifier", +// BLOCKPTR-NEXT: "preciseIdentifier": "c:typedef.c@T@CustomType", +// BLOCKPTR-NEXT: "spelling": "CustomType" +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "text", +// BLOCKPTR-NEXT: "spelling": " " +// BLOCKPTR-NEXT: }, +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "internalParam", +// BLOCKPTR-NEXT: "spelling": "block" +// BLOCKPTR-NEXT: } +// BLOCKPTR-NEXT: ], +// BLOCKPTR-NEXT: "name": "block" +// BLOCKPTR-NEXT: } +// BLOCKPTR-NEXT: ], +// BLOCKPTR-NEXT: "returns": [ +// BLOCKPTR-NEXT: { +// BLOCKPTR-NEXT: "kind": "typeIdentifier", +// BLOCKPTR-NEXT: "preciseIdentifier": "c:v", +// BLOCKPTR-NEXT: "spelling": "void" +// BLOCKPTR-NEXT: } +// BLOCKPTR-NEXT: ] +// BLOCKPTR-NEXT: }, +// BLOCKPTR: "identifier": { +// BLOCKPTR-NEXT: "interfaceLanguage": "objective-c", +// BLOCKPTR-NEXT: "precise": "c:@F@bar" +// BLOCKPTR-NEXT: }, +// BLOCKPTR: "kind": { +// BLOCKPTR-NEXT: "displayName": "Function", +// BLOCKPTR-NEXT: "identifier": "objective-c.func" +// BLOCKPTR-NEXT: }, + // expected-no-diagnostics diff --git a/clang/test/Modules/ExtDebugInfo.cpp b/clang/test/Modules/ExtDebugInfo.cpp index 184973bc1783c..3e74e2291d5e4 100644 --- a/clang/test/Modules/ExtDebugInfo.cpp +++ b/clang/test/Modules/ExtDebugInfo.cpp @@ -8,7 +8,7 @@ // RUN: -fmodule-format=obj -fimplicit-module-maps -DMODULES \ // RUN: -triple %itanium_abi_triple \ // RUN: -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t-mod.ll -// RUN: cat %t-mod.ll | FileCheck %s +// RUN: cat %t-mod.ll | FileCheck %s --check-prefix=CHECK %if target={{.*-(win|mingw|cyg).*}} %{--check-prefix=CHECKCOFF%} %else %{--check-prefix=CHECKELF%} // PCH: // RUN: %clang_cc1 -x c++ -std=c++11 -fmodule-format=obj -emit-pch -I%S/Inputs \ @@ -18,7 +18,7 @@ // RUN: -dwarf-ext-refs -fmodule-format=obj \ // RUN: -triple %itanium_abi_triple \ // RUN: -include-pch %t.pch %s -emit-llvm -o %t-pch.ll -// RUN: cat %t-pch.ll | FileCheck %s +// RUN: cat %t-pch.ll | FileCheck %s --check-prefix=CHECK %if target={{.*-(win|mingw|cyg).*}} %{--check-prefix=CHECKCOFF%} %else %{--check-prefix=CHECKELF%} // RUN: cat %t-pch.ll | FileCheck %s --check-prefix=CHECK-PCH #ifdef MODULES @@ -208,9 +208,9 @@ void foo() { // CHECK-SAME: name: "InAnonymousNamespace", {{.*}}DIFlagFwdDecl) // There is a full definition of the type available in the module. -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual", -// CHECK-SAME: DIFlagFwdDecl -// CHECK-SAME: identifier: "_ZTS7Virtual") +// CHECKELF: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual", +// CHECKELF-SAME: DIFlagFwdDecl +// CHECKELF-SAME: identifier: "_ZTS7Virtual") // CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !{{[0-9]+}}, entity: ![[STRUCT]], file: ![[CPP]], line: 50) @@ -222,3 +222,8 @@ void foo() { // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A", // CHECK-SAME: DIFlagFwdDecl + +// There is a full definition of the type available in the module. +// CHECKCOFF: !DICompositeType(tag: DW_TAG_structure_type, name: "Virtual", +// CHECKCOFF-SAME: DIFlagFwdDecl +// CHECKCOFF-SAME: identifier: "_ZTS7Virtual") diff --git a/clang/test/Modules/crash-enum-visibility-with-header-unit.cppm b/clang/test/Modules/crash-enum-visibility-with-header-unit.cppm new file mode 100644 index 0000000000000..90c57796dcf7e --- /dev/null +++ b/clang/test/Modules/crash-enum-visibility-with-header-unit.cppm @@ -0,0 +1,46 @@ +// Fixes #165445 + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -x c++-user-header %t/header.h \ +// RUN: -emit-header-unit -o %t/header.pcm +// +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -fmodule-file=%t/header.pcm \ +// RUN: -emit-module-interface -o %t/A.pcm +// +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=%t/header.pcm \ +// RUN: -emit-module-interface -o %t/B.pcm +// +// RUN: %clang_cc1 -std=c++20 %t/use.cpp \ +// RUN: -fmodule-file=A=%t/A.pcm -fmodule-file=B=%t/B.pcm \ +// RUN: -fmodule-file=%t/header.pcm \ +// RUN: -verify -fsyntax-only + +//--- enum.h +enum E { Value }; + +//--- header.h +#include "enum.h" + +//--- A.cppm +module; +#include "enum.h" +export module A; + +auto e = Value; + +//--- B.cppm +export module B; +import "header.h"; + +auto e = Value; + +//--- use.cpp +// expected-no-diagnostics +import A; +import B; +#include "enum.h" + +auto e = Value; diff --git a/clang/test/Modules/fmodules-validate-once-per-build-session.c b/clang/test/Modules/fmodules-validate-once-per-build-session.c index d9d79b001e30c..2348ca1381e8a 100644 --- a/clang/test/Modules/fmodules-validate-once-per-build-session.c +++ b/clang/test/Modules/fmodules-validate-once-per-build-session.c @@ -1,119 +1,134 @@ -#include "foo.h" -#include "bar.h" - -// Clear the module cache. -// RUN: rm -rf %t -// RUN: mkdir -p %t/Inputs -// RUN: mkdir -p %t/modules-to-compare +// This tests the behavior of -fmodules-validate-once-per-build-session with +// different combinations of flags and states of the module cache. -// === -// Create a module. We will use -I or -isystem to determine whether to treat -// foo.h as a system header. -// RUN: echo 'void meow(void);' > %t/Inputs/foo.h -// RUN: echo 'void woof(void);' > %t/Inputs/bar.h -// RUN: echo 'module Foo { header "foo.h" }' > %t/Inputs/module.modulemap -// RUN: echo 'extern module Bar "bar.modulemap"' >> %t/Inputs/module.modulemap -// RUN: echo 'module Bar { header "bar.h" }' > %t/Inputs/bar.modulemap +// Note: The `sleep 1` commands sprinkled throughout this test make the strict +// comparisons of epoch mtimes work as expected. Some may be unnecessary, +// but make the intent clearer. -// === -// Compile the module. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user-no-force -fsyntax-only -I %t/Inputs -fno-modules-force-validate-user-headers -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Bar.pcm.timestamp -// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-before.pcm -// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-before.pcm -// RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-before-user.pcm -// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-before-user.pcm -// RUN: cp %t/modules-cache-user-no-force/Foo.pcm %t/modules-to-compare/Foo-before-user-no-force.pcm -// RUN: cp %t/modules-cache-user-no-force/Bar.pcm %t/modules-to-compare/Bar-before-user-no-force.pcm - -// === -// Use it, and make sure that we did not recompile it. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-use-no-force -fsyntax-only -I %t/Inputs -fno-modules-force-validate-user-headers -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Bar.pcm.timestamp -// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-after.pcm -// RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-after-user.pcm -// RUN: cp %t/modules-cache-user-no-force/Foo.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: cp %t/modules-cache-user-no-force/Bar.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: echo "-fsyntax-only -fmodules -fmodules-cache-path=%/t/module-cache" > %t/ctx.rsp +// RUN: echo "-fbuild-session-file=%/t/module-cache/session.timestamp" >> %t/ctx.rsp +// RUN: echo "-fmodules-validate-once-per-build-session" >> %t/ctx.rsp +// RUN: echo "-Rmodule-build -Rmodule-validation" >> %t/ctx.rsp -// RUN: diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: diff %t/modules-to-compare/Bar-before.pcm %t/modules-to-compare/Bar-after.pcm -// RUN: diff %t/modules-to-compare/Foo-before-user.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: diff %t/modules-to-compare/Bar-before-user.pcm %t/modules-to-compare/Bar-after-user.pcm -// RUN: diff %t/modules-to-compare/Foo-before-user-no-force.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: diff %t/modules-to-compare/Bar-before-user-no-force.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +//--- include/foo.h +//--- include/module.modulemap +module Foo { header "foo.h" } -// === -// Change the sources. +//--- clean.c +// Clean module cache. Modules will get compiled regardless of validation settings. +// RUN: mkdir %t/module-cache // RUN: sleep 1 -// RUN: echo 'void meow2(void);' > %t/Inputs/foo.h -// RUN: echo 'module Bar { header "bar.h" export * }' > %t/Inputs/bar.modulemap +// RUN: touch %t/module-cache/session.timestamp +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/clean.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/clean.c +// RUN: %clang @%t/ctx.rsp %t/clean.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/clean.c +// RUN: %clang @%t/ctx.rsp %t/clean.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/clean.c +#include "foo.h" +// CHECK: building module 'Foo' -// === -// Use the module, and make sure that we did not recompile it if foo.h or -// module.modulemap are system files or user files with force validation disabled, -// even though the sources changed. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user-no-force -fsyntax-only -I %t/Inputs -fno-modules-force-validate-user-headers -fmodules-validate-system-headers -fbuild-session-timestamp=1390000000 -fmodules-validate-once-per-build-session %s -// RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Bar.pcm.timestamp -// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-after.pcm -// RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-after-user.pcm -// RUN: cp %t/modules-cache-user-no-force/Foo.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: cp %t/modules-cache-user-no-force/Bar.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +//--- no-change-same-session.c +// Populated module cache in the same build session with unchanged inputs. +// Validation only happens when it's forced for user headers. No compiles. +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/no-change-same-session.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-same-session.c --check-prefix=CHECK-NO-VALIDATION-OR-BUILD --allow-empty +// RUN: %clang @%t/ctx.rsp %t/no-change-same-session.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-same-session.c --check-prefix=CHECK-VALIDATION-ONLY +// RUN: %clang @%t/ctx.rsp %t/no-change-same-session.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-same-session.c --check-prefix=CHECK-NO-VALIDATION-OR-BUILD --allow-empty +#include "foo.h" +// CHECK-NO-VALIDATION-OR-BUILD-NOT: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-NO-VALIDATION-OR-BUILD-NOT: building module 'Foo' +// CHECK-VALIDATION-ONLY: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-VALIDATION-ONLY-NOT: building module 'Foo' -// RUN: diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: diff %t/modules-to-compare/Bar-before.pcm %t/modules-to-compare/Bar-after.pcm -// When foo.h is an user header, we will validate it by default. -// RUN: not diff %t/modules-to-compare/Foo-before-user.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: not diff %t/modules-to-compare/Bar-before-user.pcm %t/modules-to-compare/Bar-after-user.pcm -// When foo.h is an user header, we will not validate it if force validation is turned off. -// RUN: diff %t/modules-to-compare/Foo-before-user-no-force.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: diff %t/modules-to-compare/Bar-before-user-no-force.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +//--- change-same-session.c +// Populated module cache in the same build session with changed inputs. +// Validation only happens when it's forced for user headers and results in compilation. +// RUN: sleep 1 +// RUN: touch %t/include/foo.h +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/change-same-session.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/change-same-session.c --check-prefix=CHECK-NO-VALIDATION-OR-BUILD --allow-empty +// RUN: %clang @%t/ctx.rsp %t/change-same-session.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/change-same-session.c --check-prefix=CHECK-VALIDATION-AND-BUILD +// RUN: %clang @%t/ctx.rsp %t/change-same-session.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/change-same-session.c --check-prefix=CHECK-NO-VALIDATION-OR-BUILD --allow-empty +#include "foo.h" +// CHECK-NO-VALIDATION-OR-BUILD-NOT: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-NO-VALIDATION-OR-BUILD-NOT: building module 'Foo' +// CHECK-VALIDATION-AND-BUILD: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-VALIDATION-AND-BUILD: building module 'Foo' -// === -// Recompile the module if the today's date is before 01 January 2100. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=4102441200 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=4102441200 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user-no-force -fsyntax-only -I %t/Inputs -fno-modules-force-validate-user-headers -fmodules-validate-system-headers -fbuild-session-timestamp=4102441200 -fmodules-validate-once-per-build-session %s -// RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Foo.pcm.timestamp -// RUN: ls -R %t/modules-cache-user-no-force | grep Bar.pcm.timestamp -// RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-after.pcm -// RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-after-user.pcm -// RUN: cp %t/modules-cache-user-no-force/Foo.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: cp %t/modules-cache-user-no-force/Bar.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +//--- change-new-session.c +// Populated module cache in a new build session with changed inputs. +// All configurations validate and recompile. +// RUN: sleep 1 +// RUN: touch %t/include/foo.h +// RUN: sleep 1 +// RUN: touch %t/module-cache/session.timestamp +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/change-new-session.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/change-new-session.c --check-prefixes=CHECK,CHECK-VALIDATE-ONCE +// NOTE: Forced user headers validation causes redundant validation of the just-built module. +// RUN: %clang @%t/ctx.rsp %t/change-new-session.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/change-new-session.c --check-prefixes=CHECK,CHECK-FORCE-VALIDATE-TWICE +// RUN: %clang @%t/ctx.rsp %t/change-new-session.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/change-new-session.c --check-prefixes=CHECK,CHECK-VALIDATE-ONCE +#include "foo.h" +// CHECK: validating {{[0-9]+}} input files in module 'Foo' +// CHECK: building module 'Foo' +// CHECK-VALIDATE-ONCE-NOT: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-FORCE-VALIDATE-TWICE: validating {{[0-9]+}} input files in module 'Foo' -// RUN: not diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm -// RUN: not diff %t/modules-to-compare/Bar-before.pcm %t/modules-to-compare/Bar-after.pcm -// RUN: not diff %t/modules-to-compare/Foo-before-user.pcm %t/modules-to-compare/Foo-after-user.pcm -// RUN: not diff %t/modules-to-compare/Bar-before-user.pcm %t/modules-to-compare/Bar-after-user.pcm -// RUN: not diff %t/modules-to-compare/Foo-before-user-no-force.pcm %t/modules-to-compare/Foo-after-user-no-force.pcm -// RUN: not diff %t/modules-to-compare/Bar-before-user-no-force.pcm %t/modules-to-compare/Bar-after-user-no-force.pcm +//--- no-change-new-session-twice.c +// Populated module cache in a new build session with unchanged inputs. +// At first, all configurations validate but don't recompile. +// RUN: sleep 1 +// RUN: touch %t/module-cache/session.timestamp +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-ONCE +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-ONCE +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-ONCE +// +// Then, only the forced user header validation performs redundant validation (but no compilation). +// All other configurations do not validate and do not compile. +// RUN: sleep 1 +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=1 \ +// RUN: -isystem %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-NOT-TWICE --allow-empty +// NOTE: Forced user headers validation causes redundant validation of the just-validated module. +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=2 \ +// RUN: -I %t/include -fmodules-validate-system-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-ONCE +// RUN: %clang @%t/ctx.rsp %t/no-change-new-session-twice.c -DCTX=3 \ +// RUN: -I %t/include -fmodules-validate-system-headers -Xclang -fno-modules-force-validate-user-headers \ +// RUN: 2>&1 | FileCheck %t/no-change-new-session-twice.c --check-prefix=CHECK-NOT-TWICE --allow-empty +#include "foo.h" +// CHECK-ONCE: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-ONCE-NOT: building module 'Foo' +// CHECK-NOT-TWICE-NOT: validating {{[0-9]+}} input files in module 'Foo' +// CHECK-NOT-TWICE-NOT: building module 'Foo' diff --git a/clang/test/Preprocessor/init-mips.c b/clang/test/Preprocessor/init-mips.c index 4fead33bd826e..125872a001bac 100644 --- a/clang/test/Preprocessor/init-mips.c +++ b/clang/test/Preprocessor/init-mips.c @@ -80,10 +80,10 @@ // MIPS32BE:#define __INTMAX_MAX__ 9223372036854775807LL // MIPS32BE:#define __INTMAX_TYPE__ long long int // MIPS32BE:#define __INTMAX_WIDTH__ 64 -// MIPS32BE:#define __INTPTR_FMTd__ "ld" -// MIPS32BE:#define __INTPTR_FMTi__ "li" -// MIPS32BE:#define __INTPTR_MAX__ 2147483647L -// MIPS32BE:#define __INTPTR_TYPE__ long int +// MIPS32BE:#define __INTPTR_FMTd__ "d" +// MIPS32BE:#define __INTPTR_FMTi__ "i" +// MIPS32BE:#define __INTPTR_MAX__ 2147483647 +// MIPS32BE:#define __INTPTR_TYPE__ int // MIPS32BE:#define __INTPTR_WIDTH__ 32 // MIPS32BE:#define __INT_FAST16_FMTd__ "hd" // MIPS32BE:#define __INT_FAST16_FMTi__ "hi" @@ -185,8 +185,8 @@ // MIPS32BE:#define __UINTMAX_MAX__ 18446744073709551615ULL // MIPS32BE:#define __UINTMAX_TYPE__ long long unsigned int // MIPS32BE:#define __UINTMAX_WIDTH__ 64 -// MIPS32BE:#define __UINTPTR_MAX__ 4294967295UL -// MIPS32BE:#define __UINTPTR_TYPE__ long unsigned int +// MIPS32BE:#define __UINTPTR_MAX__ 4294967295U +// MIPS32BE:#define __UINTPTR_TYPE__ unsigned int // MIPS32BE:#define __UINTPTR_WIDTH__ 32 // MIPS32BE:#define __UINT_FAST16_MAX__ 65535 // MIPS32BE:#define __UINT_FAST16_TYPE__ unsigned short @@ -300,10 +300,10 @@ // MIPS32EL:#define __INTMAX_MAX__ 9223372036854775807LL // MIPS32EL:#define __INTMAX_TYPE__ long long int // MIPS32EL:#define __INTMAX_WIDTH__ 64 -// MIPS32EL:#define __INTPTR_FMTd__ "ld" -// MIPS32EL:#define __INTPTR_FMTi__ "li" -// MIPS32EL:#define __INTPTR_MAX__ 2147483647L -// MIPS32EL:#define __INTPTR_TYPE__ long int +// MIPS32EL:#define __INTPTR_FMTd__ "d" +// MIPS32EL:#define __INTPTR_FMTi__ "i" +// MIPS32EL:#define __INTPTR_MAX__ 2147483647 +// MIPS32EL:#define __INTPTR_TYPE__ int // MIPS32EL:#define __INTPTR_WIDTH__ 32 // MIPS32EL:#define __INT_FAST16_FMTd__ "hd" // MIPS32EL:#define __INT_FAST16_FMTi__ "hi" @@ -402,8 +402,8 @@ // MIPS32EL:#define __UINTMAX_MAX__ 18446744073709551615ULL // MIPS32EL:#define __UINTMAX_TYPE__ long long unsigned int // MIPS32EL:#define __UINTMAX_WIDTH__ 64 -// MIPS32EL:#define __UINTPTR_MAX__ 4294967295UL -// MIPS32EL:#define __UINTPTR_TYPE__ long unsigned int +// MIPS32EL:#define __UINTPTR_MAX__ 4294967295U +// MIPS32EL:#define __UINTPTR_TYPE__ unsigned int // MIPS32EL:#define __UINTPTR_WIDTH__ 32 // MIPS32EL:#define __UINT_FAST16_MAX__ 65535 // MIPS32EL:#define __UINT_FAST16_TYPE__ unsigned short @@ -547,10 +547,10 @@ // MIPSN32BE: #define __INTMAX_MAX__ 9223372036854775807LL // MIPSN32BE: #define __INTMAX_TYPE__ long long int // MIPSN32BE: #define __INTMAX_WIDTH__ 64 -// MIPSN32BE: #define __INTPTR_FMTd__ "ld" -// MIPSN32BE: #define __INTPTR_FMTi__ "li" -// MIPSN32BE: #define __INTPTR_MAX__ 2147483647L -// MIPSN32BE: #define __INTPTR_TYPE__ long int +// MIPSN32BE: #define __INTPTR_FMTd__ "d" +// MIPSN32BE: #define __INTPTR_FMTi__ "i" +// MIPSN32BE: #define __INTPTR_MAX__ 2147483647 +// MIPSN32BE: #define __INTPTR_TYPE__ int // MIPSN32BE: #define __INTPTR_WIDTH__ 32 // MIPSN32BE: #define __INT_FAST16_FMTd__ "hd" // MIPSN32BE: #define __INT_FAST16_FMTi__ "hi" @@ -684,12 +684,12 @@ // MIPSN32BE: #define __UINTMAX_MAX__ 18446744073709551615ULL // MIPSN32BE: #define __UINTMAX_TYPE__ long long unsigned int // MIPSN32BE: #define __UINTMAX_WIDTH__ 64 -// MIPSN32BE: #define __UINTPTR_FMTX__ "lX" -// MIPSN32BE: #define __UINTPTR_FMTo__ "lo" -// MIPSN32BE: #define __UINTPTR_FMTu__ "lu" -// MIPSN32BE: #define __UINTPTR_FMTx__ "lx" -// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295UL -// MIPSN32BE: #define __UINTPTR_TYPE__ long unsigned int +// MIPSN32BE: #define __UINTPTR_FMTX__ "X" +// MIPSN32BE: #define __UINTPTR_FMTo__ "o" +// MIPSN32BE: #define __UINTPTR_FMTu__ "u" +// MIPSN32BE: #define __UINTPTR_FMTx__ "x" +// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295U +// MIPSN32BE: #define __UINTPTR_TYPE__ unsigned int // MIPSN32BE: #define __UINTPTR_WIDTH__ 32 // MIPSN32BE: #define __UINT_FAST16_FMTX__ "hX" // MIPSN32BE: #define __UINT_FAST16_FMTo__ "ho" @@ -864,10 +864,10 @@ // MIPSN32EL: #define __INTMAX_MAX__ 9223372036854775807LL // MIPSN32EL: #define __INTMAX_TYPE__ long long int // MIPSN32EL: #define __INTMAX_WIDTH__ 64 -// MIPSN32EL: #define __INTPTR_FMTd__ "ld" -// MIPSN32EL: #define __INTPTR_FMTi__ "li" -// MIPSN32EL: #define __INTPTR_MAX__ 2147483647L -// MIPSN32EL: #define __INTPTR_TYPE__ long int +// MIPSN32EL: #define __INTPTR_FMTd__ "d" +// MIPSN32EL: #define __INTPTR_FMTi__ "i" +// MIPSN32EL: #define __INTPTR_MAX__ 2147483647 +// MIPSN32EL: #define __INTPTR_TYPE__ int // MIPSN32EL: #define __INTPTR_WIDTH__ 32 // MIPSN32EL: #define __INT_FAST16_FMTd__ "hd" // MIPSN32EL: #define __INT_FAST16_FMTi__ "hi" @@ -1001,12 +1001,12 @@ // MIPSN32EL: #define __UINTMAX_MAX__ 18446744073709551615ULL // MIPSN32EL: #define __UINTMAX_TYPE__ long long unsigned int // MIPSN32EL: #define __UINTMAX_WIDTH__ 64 -// MIPSN32EL: #define __UINTPTR_FMTX__ "lX" -// MIPSN32EL: #define __UINTPTR_FMTo__ "lo" -// MIPSN32EL: #define __UINTPTR_FMTu__ "lu" -// MIPSN32EL: #define __UINTPTR_FMTx__ "lx" -// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295UL -// MIPSN32EL: #define __UINTPTR_TYPE__ long unsigned int +// MIPSN32EL: #define __UINTPTR_FMTX__ "X" +// MIPSN32EL: #define __UINTPTR_FMTo__ "o" +// MIPSN32EL: #define __UINTPTR_FMTu__ "u" +// MIPSN32EL: #define __UINTPTR_FMTx__ "x" +// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295U +// MIPSN32EL: #define __UINTPTR_TYPE__ unsigned int // MIPSN32EL: #define __UINTPTR_WIDTH__ 32 // MIPSN32EL: #define __UINT_FAST16_FMTX__ "hX" // MIPSN32EL: #define __UINT_FAST16_FMTo__ "ho" diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index bed39dc3e34dc..7e0df96141364 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -1622,6 +1622,14 @@ // RUN: %clang_cc1 -x c -std=c99 -E -dM -ffreestanding -triple=amd64-unknown-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD-STDC-N %s // OPENBSD-STDC-N-NOT:#define __STDC_NO_THREADS__ 1 // +// RUN: %clang_cc1 -x c -std=c11 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s +// RUN: %clang_cc1 -x c -std=gnu11 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s +// RUN: %clang_cc1 -x c -std=c17 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC %s +// DRAGONFLY-STDC:#define __STDC_NO_THREADS__ 1 +// +// RUN: %clang_cc1 -x c -std=c99 -E -dM -ffreestanding -triple=x86_64-unknown-dragonfly < /dev/null | FileCheck -match-full-lines -check-prefix DRAGONFLY-STDC-N %s +// DRAGONFLY-STDC-N-NOT:#define __STDC_NO_THREADS__ 1 +// // RUN: %clang_cc1 -triple=aarch64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s // RUN: %clang_cc1 -triple=riscv64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s // RUN: %clang_cc1 -triple=x86_64-unknown-managarm-mlibc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MANAGARM %s diff --git a/clang/test/Preprocessor/ptrauth_extension.c b/clang/test/Preprocessor/ptrauth_extension.c index d6b79187ba62d..3267b0786c28f 100644 --- a/clang/test/Preprocessor/ptrauth_extension.c +++ b/clang/test/Preprocessor/ptrauth_extension.c @@ -4,10 +4,32 @@ // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-calls | \ // RUN: FileCheck %s --check-prefixes=NOINTRIN -#if __has_extension(ptrauth_qualifier) -// INTRIN: has_ptrauth_qualifier -void has_ptrauth_qualifier() {} -#else +// RUN: %clang_cc1 -E %s -DIS_DARWIN -triple=arm64e-apple-darwin -fptrauth-intrinsics | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,INTRIN_MAC + +// RUN: %clang_cc1 -E %s -DIS_DARWIN -triple=arm64e-apple-darwin -fptrauth-calls | \ +// RUN: FileCheck %s --check-prefixes=NOINTRIN + +#if defined(IS_DARWIN) && __has_extension(ptrauth_qualifier) +// INTRIN_MAC: has_ptrauth_qualifier1 +void has_ptrauth_qualifier1() {} +#ifndef __PTRAUTH__ +#error ptrauth_qualifier extension present without predefined test macro +#endif +#endif +#if defined(IS_DARWIN) && __has_feature(ptrauth_qualifier) +// INTRIN_MAC: has_ptrauth_qualifier2 +void has_ptrauth_qualifier2() {} +#ifndef __PTRAUTH__ +#error ptrauth_qualifier extension present without predefined test macro +#endif +#endif +#if defined(__PTRAUTH__) +// INTRIN: has_ptrauth_qualifier3 +void has_ptrauth_qualifier3() {} +#endif + +#if !defined(__PTRAUTH__) && !__has_feature(ptrauth_qualifier) && !__has_extension(ptrauth_qualifier) // NOINTRIN: no_ptrauth_qualifier void no_ptrauth_qualifier() {} #endif diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index a440791d6cc69..cebea4188415f 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -34,7 +34,7 @@ // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-elf-got | \ // RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,ELFGOT -#if __has_feature(ptrauth_intrinsics) +#if defined(__PTRAUTH__) // INTRIN: has_ptrauth_intrinsics void has_ptrauth_intrinsics() {} #else @@ -130,3 +130,11 @@ void has_ptrauth_elf_got() {} // NOELFGOT: no_ptrauth_elf_got void no_ptrauth_elf_got() {} #endif + +#if __has_feature(ptrauth_objc_signable_class) +// INTRIN: has_ptrauth_objc_signable_class +void has_ptrauth_objc_signable_class(){} +#else +// NOINTRIN: no_ptrauth_objc_signable_class +void no_ptrauth_objc_signable_class(){} +#endif diff --git a/clang/test/Preprocessor/stdint.c b/clang/test/Preprocessor/stdint.c index 899ff59bf0b6a..9f982a3a94fd6 100644 --- a/clang/test/Preprocessor/stdint.c +++ b/clang/test/Preprocessor/stdint.c @@ -350,8 +350,8 @@ // MIPS:typedef int8_t int_fast8_t; // MIPS:typedef uint8_t uint_fast8_t; // -// MIPS:typedef long int intptr_t; -// MIPS:typedef long unsigned int uintptr_t; +// MIPS:typedef int intptr_t; +// MIPS:typedef unsigned int uintptr_t; // // MIPS:typedef long long int intmax_t; // MIPS:typedef long long unsigned int uintmax_t; @@ -396,9 +396,9 @@ // MIPS:INT_FAST64_MAX_ 9223372036854775807LL // MIPS:UINT_FAST64_MAX_ 18446744073709551615ULL // -// MIPS:INTPTR_MIN_ (-2147483647L -1) -// MIPS:INTPTR_MAX_ 2147483647L -// MIPS:UINTPTR_MAX_ 4294967295UL +// MIPS:INTPTR_MIN_ (-2147483647 -1) +// MIPS:INTPTR_MAX_ 2147483647 +// MIPS:UINTPTR_MAX_ 4294967295U // MIPS:PTRDIFF_MIN_ (-2147483647 -1) // MIPS:PTRDIFF_MAX_ 2147483647 // MIPS:SIZE_MAX_ 4294967295U diff --git a/clang/test/Sema/attr-nonstring.c b/clang/test/Sema/attr-nonstring.c index 3838aa3bbee15..fe7b6d259dd79 100644 --- a/clang/test/Sema/attr-nonstring.c +++ b/clang/test/Sema/attr-nonstring.c @@ -229,3 +229,11 @@ struct Outer o2[] = { } } }; + +// The attribute also works with a pointer type, not just an array type. +__attribute__((nonstring)) char *ptr1; +__attribute__((nonstring)) const unsigned char *ptr2; +struct GH150951 { + __attribute__((nonstring)) char *ptr1; + __attribute__((nonstring)) const unsigned char *ptr2; +}; diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c index 3dcb0b3a7d95f..0987d175c91a8 100644 --- a/clang/test/Sema/constexpr.c +++ b/clang/test/Sema/constexpr.c @@ -391,3 +391,10 @@ void ghissue109095() { _Static_assert(i == c[0]); // expected-error {{static assertion expression is not an integral constant expression}}\ // expected-note {{initializer of 'i' is not a constant expression}} } + +typedef bool __vbool2 __attribute__((ext_vector_type(2))); +typedef short v2int16_t __attribute__((ext_vector_type(2))); + +bool issue155507(v2int16_t a, v2int16_t b) { + return __builtin_bit_cast(unsigned char, __builtin_convertvector(a == b, __vbool2)) == 0b11; +} diff --git a/clang/test/Sema/for.c b/clang/test/Sema/for.c index e16169aac0c4c..35c4720ef3305 100644 --- a/clang/test/Sema/for.c +++ b/clang/test/Sema/for.c @@ -26,6 +26,5 @@ void b11 (void) { for (static _Thread_local struct { int i; } s;s.i;); } /* c11- #endif void b12(void) { - for(_Static_assert(1, "");;) {} /* c11-warning {{non-variable declaration in 'for' loop is a C23 extension}} - c23-warning {{non-variable declaration in 'for' loop is incompatible with C standards before C23}} */ + for(_Static_assert(1, "");;) {} /* okay, _Static_assert declares *no* identifiers */ } diff --git a/clang/test/Sema/implicit-void-ptr-cast.c b/clang/test/Sema/implicit-void-ptr-cast.c index 3c3e153d1dbda..d5e9497191446 100644 --- a/clang/test/Sema/implicit-void-ptr-cast.c +++ b/clang/test/Sema/implicit-void-ptr-cast.c @@ -82,3 +82,15 @@ void more(void) { ptr3 = SOMETHING_THAT_IS_NOT_NULL; // c-warning {{implicit conversion when assigning to 'char *' from type 'void *' is not permitted in C++}} \ cxx-error {{assigning to 'char *' from incompatible type 'void *'}} } + +void gh154157(void) { + #define ATOMIC_VAR_INIT(value) (value) + + typedef const struct T * T_Ref; + static T_Ref _Atomic x = ATOMIC_VAR_INIT((void*)NULL); // c-warning {{implicit conversion when initializing '_Atomic(T_Ref)' with an expression of type 'void *' is not permitted in C++}} \ + cxx-error {{cannot initialize a variable of type '_Atomic(T_Ref)' with an rvalue of type 'void *'}} + static T_Ref const y = ATOMIC_VAR_INIT((void*)NULL); // c-warning {{implicit conversion when initializing 'const T_Ref' (aka 'const struct T *const') with an expression of type 'void *' is not permitted in C++}} \ + cxx-error {{cannot initialize a variable of type 'const T_Ref' (aka 'const T *const') with an rvalue of type 'void *'}} + static T_Ref z = ATOMIC_VAR_INIT((void*)NULL); // c-warning {{implicit conversion when initializing 'T_Ref' (aka 'const struct T *') with an expression of type 'void *' is not permitted in C++}} \ + cxx-error {{cannot initialize a variable of type 'T_Ref' (aka 'const T *') with an rvalue of type 'void *'}} +} diff --git a/clang/test/Sema/ptrauth-qualifier.c b/clang/test/Sema/ptrauth-qualifier.c index 5d932b724f07a..3e568ce9f37e3 100644 --- a/clang/test/Sema/ptrauth-qualifier.c +++ b/clang/test/Sema/ptrauth-qualifier.c @@ -1,13 +1,25 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s +// RUN: %clang_cc1 -triple arm64-apple-ios -DIS_DARWIN -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s // RUN: %clang_cc1 -triple aarch64-linux-gnu -std=c23 -fsyntax-only -verify -fptrauth-intrinsics %s -#if !__has_extension(ptrauth_qualifier) +#if defined(IS_DARWIN) && !__has_extension(ptrauth_qualifier) // This error means that the __ptrauth qualifier availability test says that it // is not available. This error is not expected in the output, if it is seen // there is a feature detection regression. #error __ptrauth qualifier not enabled #endif +#if defined(IS_DARWIN) && !__has_feature(ptrauth_qualifier) +// This error means that the __has_feature test for ptrauth_qualifier has +// failed, despite it being expected on darwin. +#error __ptrauth qualifier not enabled +#elif !defined(IS_DARWIN) && (__has_feature(ptrauth_qualifier) || __has_extension(ptrauth_qualifier)) +#error ptrauth_qualifier labeled a feature on a non-darwin platform +#endif + +#if !defined (__PTRAUTH__) +#error __PTRAUTH__ test macro not defined when ptrauth is enabled +#endif + #if __aarch64__ #define VALID_CODE_KEY 0 #define VALID_DATA_KEY 2 diff --git a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp index 38dfdb98f08fc..a956386ae9332 100644 --- a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp +++ b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -mllvm -debug-only=LifetimeFacts,LifetimeDataflow -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fexperimental-lifetime-safety -mllvm -debug-only=LifetimeFacts,LifetimeDataflow -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s // REQUIRES: asserts struct MyObj { diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index c390fee1c38d9..935409131e18f 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2615,3 +2615,19 @@ namespace DoubleCapture { }; } } + +namespace GH154567 { + struct T { + int i; + }; + + struct S { + struct { // expected-warning {{GNU extension}} + T val; + }; + constexpr S() : val() {} + }; + + constexpr S s{}; + static_assert(s.val.i == 0, ""); +} diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index e16a69df3830d..e93b98c185a82 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -1321,3 +1321,18 @@ constexpr bool check = different_in_loop(); // expected-error@-1 {{}} expected-note@-1 {{in call}} } + +namespace comparison_dead_variable { + constexpr bool f() { + int *p1 = 0, *p2 = 0; + { + int x = 0; p1 = &x; + } + { + int x = 0; p2 = &x; + } + return p1 != p2; + } + // FIXME: This should fail. + static_assert(f(),""); +} diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index dffb386f530f4..312a77830420b 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -319,7 +319,7 @@ namespace casting { } namespace pointer_comparisons { - extern int &extern_n; // interpreter-note 2 {{declared here}} + extern int &extern_n; // interpreter-note 4 {{declared here}} extern int &extern_n2; constexpr int f1(bool b, int& n) { if (b) { @@ -330,14 +330,70 @@ namespace pointer_comparisons { // FIXME: interpreter incorrectly rejects; both sides are the same constexpr-unknown value. static_assert(f1(false, extern_n)); // interpreter-error {{static assertion expression is not an integral constant expression}} \ // interpreter-note {{initializer of 'extern_n' is unknown}} - // FIXME: We should diagnose this: we don't know if the references bind - // to the same object. - static_assert(&extern_n != &extern_n2); // interpreter-error {{static assertion expression is not an integral constant expression}} \ + static_assert(&extern_n != &extern_n2); // expected-error {{static assertion expression is not an integral constant expression}} \ + // nointerpreter-note {{comparison between pointers to unrelated objects '&extern_n' and '&extern_n2' has unspecified value}} \ // interpreter-note {{initializer of 'extern_n' is unknown}} void f2(const int &n) { - // FIXME: We should not diagnose this: the two objects provably have - // different addresses because the lifetime of "n" extends across - // the initialization. - constexpr int x = &x == &n; // nointerpreter-error {{must be initialized by a constant expression}} + constexpr int x = &x == &n; // nointerpreter-error {{must be initialized by a constant expression}} \ + // nointerpreter-note {{comparison between pointers to unrelated objects '&x' and '&n' has unspecified value}} + // Distinct variables are not equal, even if they're local variables. + constexpr int y = &x == &y; + static_assert(!y); } + constexpr int f3() { + int x; + return &x == &extern_n; // nointerpreter-note {{comparison between pointers to unrelated objects '&x' and '&extern_n' has unspecified value}} \ + // interpreter-note {{initializer of 'extern_n' is unknown}} + } + static_assert(!f3()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f3()'}} + constexpr int f4() { + int *p = new int; + bool b = p == &extern_n; // nointerpreter-note {{comparison between pointers to unrelated objects '&{*new int#0}' and '&extern_n' has unspecified value}} \ + // interpreter-note {{initializer of 'extern_n' is unknown}} + delete p; + return b; + } + static_assert(!f4()); // expected-error {{static assertion expression is not an integral constant expression}} \ + // expected-note {{in call to 'f4()'}} +} + +namespace GH149188 { +namespace enable_if_1 { + template <__SIZE_TYPE__ N> + constexpr void foo(const char (&Str)[N]) + __attribute((enable_if(__builtin_strlen(Str), ""))) {} + + void x() { + foo("1234"); + } +} + +namespace enable_if_2 { + constexpr const char (&f())[]; + extern const char (&Str)[]; + constexpr int foo() + __attribute((enable_if(__builtin_strlen(Str), ""))) + {return __builtin_strlen(Str);} + + constexpr const char (&f())[] {return "a";} + constexpr const char (&Str)[] = f(); + void x() { + constexpr int x = foo(); + } +} +} + +namespace GH150015 { + extern int (& c)[8]; // interpreter-note {{declared here}} + constexpr int x = c <= c+8; // interpreter-error {{constexpr variable 'x' must be initialized by a constant expression}} \ + // interpreter-note {{initializer of 'c' is unknown}} + + struct X {}; + struct Y {}; + struct Z : X, Y {}; + extern Z &z; // interpreter-note{{declared here}} + constexpr int bases = (void*)(X*)&z <= (Y*)&z; // expected-error {{constexpr variable 'bases' must be initialized by a constant expression}} \ + // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}} \ + // interpreter-note {{initializer of 'z' is unknown}} } diff --git a/clang/test/SemaCXX/constexpr-never-constant.cpp b/clang/test/SemaCXX/constexpr-never-constant.cpp index 307810ee263dd..5756bb647ce88 100644 --- a/clang/test/SemaCXX/constexpr-never-constant.cpp +++ b/clang/test/SemaCXX/constexpr-never-constant.cpp @@ -24,3 +24,10 @@ constexpr void other_func() { throw 12; } + +namespace GH149041 { + // Make sure these don't trigger the diagnostic. + extern const bool& b; + constexpr bool fun1() { return b; } + constexpr bool fun2(const bool& b) { return b; } +} diff --git a/clang/test/SemaCXX/noreturn-weverything.c b/clang/test/SemaCXX/noreturn-weverything.c new file mode 100644 index 0000000000000..92a587d395639 --- /dev/null +++ b/clang/test/SemaCXX/noreturn-weverything.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only %s -Weverything + +void free(void *); +typedef void (*set_free_func)(void *); +struct Method { + int nparams; + int *param; +}; +void selelem_free_method(struct Method* method, void* data) { + set_free_func free_func = 0; + for (int i = 0; i < method->nparams; ++i) + free(&method->param[i]); + if (data && free_func) + free_func(data); +} diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp index 135865c8450f5..46c3670848529 100644 --- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp +++ b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp @@ -283,31 +283,3 @@ void f() { } #endif - -namespace GH147374 { - -struct String {}; -template void operator+(T, String &&) = delete; - -struct Bar { - void operator+(String) const; // expected-note {{candidate function}} - friend void operator+(Bar, String) {}; // expected-note {{candidate function}} -}; - -struct Baz { - void operator+(String); // expected-note {{candidate function}} - friend void operator+(Baz, String) {}; // expected-note {{candidate function}} -}; - -void test() { - Bar a; - String b; - a + b; - //expected-error@-1 {{use of overloaded operator '+' is ambiguous (with operand types 'Bar' and 'String')}} - - Baz z; - z + b; - //expected-error@-1 {{use of overloaded operator '+' is ambiguous (with operand types 'Baz' and 'String')}} -} - -} diff --git a/clang/test/SemaCXX/ptrauth-triviality.cpp b/clang/test/SemaCXX/ptrauth-triviality.cpp index ba8a8273d5c05..b1b334b59a59e 100644 --- a/clang/test/SemaCXX/ptrauth-triviality.cpp +++ b/clang/test/SemaCXX/ptrauth-triviality.cpp @@ -74,7 +74,7 @@ static_assert(__is_trivially_destructible(S3)); static_assert(!__is_trivially_copyable(S3)); static_assert(!__is_trivially_relocatable(S3)); // expected-warning{{deprecated}} //FIXME -static_assert(__builtin_is_cpp_trivially_relocatable(S3)); +static_assert(!__builtin_is_cpp_trivially_relocatable(S3)); static_assert(!__is_trivially_equality_comparable(S3)); @@ -84,7 +84,7 @@ static_assert(!__is_trivially_assignable(Holder, const Holder&)); static_assert(__is_trivially_destructible(Holder)); static_assert(!__is_trivially_copyable(Holder)); static_assert(!__is_trivially_relocatable(Holder)); // expected-warning{{deprecated}} -static_assert(__builtin_is_cpp_trivially_relocatable(Holder)); +static_assert(!__builtin_is_cpp_trivially_relocatable(Holder)); static_assert(!__is_trivially_equality_comparable(Holder)); struct IA S4 { @@ -207,7 +207,7 @@ template struct UnionWrapper trivially_relocatable_if_eligible { } u; }; -static_assert(test_is_trivially_relocatable_v); +static_assert(!test_is_trivially_relocatable_v); static_assert(test_is_trivially_relocatable_v); static_assert(inheritance_relocatability_matches_bases_v); static_assert(inheritance_relocatability_matches_bases_v); diff --git a/clang/test/SemaCXX/ptrauth-type-traits.cpp b/clang/test/SemaCXX/ptrauth-type-traits.cpp new file mode 100644 index 0000000000000..a81ef1cce25b6 --- /dev/null +++ b/clang/test/SemaCXX/ptrauth-type-traits.cpp @@ -0,0 +1,437 @@ +// RUN: %clang_cc1 -triple arm64 -std=c++26 -Wno-deprecated-builtins \ +// RUN: -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple arm64-apple-darwin -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -std=c++26 -Wno-deprecated-builtins \ +// RUN: -fsyntax-only -verify %s + +// expected-no-diagnostics + +#ifdef __PTRAUTH__ +#define PTRAUTH_ENABLED 1 +#define NonAddressDiscriminatedVTablePtrAttr \ + [[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]] +#define AddressDiscriminatedVTablePtrAttr \ + [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, no_extra_discrimination)]] +#define ADDR_DISC_ENABLED true +#else +#define PTRAUTH_ENABLED 0 +#define NonAddressDiscriminatedVTablePtrAttr +#define AddressDiscriminatedVTablePtrAttr +#define ADDR_DISC_ENABLED false +#define __ptrauth(...) +#endif + + +typedef int* __ptrauth(1,1,1) AddressDiscriminatedPtr; +typedef __UINT64_TYPE__ __ptrauth(1,1,1) AddressDiscriminatedInt64; +struct AddressDiscriminatedFields { + AddressDiscriminatedPtr ptr; +}; +struct RelocatableAddressDiscriminatedFields trivially_relocatable_if_eligible { + AddressDiscriminatedPtr ptr; +}; +struct AddressDiscriminatedFieldInBaseClass : AddressDiscriminatedFields { + void *newfield; +}; + +struct NonAddressDiscriminatedVTablePtrAttr NonAddressDiscriminatedVTablePtr { + virtual ~NonAddressDiscriminatedVTablePtr(); + void *i; +}; + +struct NonAddressDiscriminatedVTablePtrAttr NonAddressDiscriminatedVTablePtr2 { + virtual ~NonAddressDiscriminatedVTablePtr2(); + void *j; +}; + +struct NonAddressDiscriminatedVTablePtrAttr RelocatableNonAddressDiscriminatedVTablePtr trivially_relocatable_if_eligible { + virtual ~RelocatableNonAddressDiscriminatedVTablePtr(); + void *i; +}; + +struct NonAddressDiscriminatedVTablePtrAttr RelocatableNonAddressDiscriminatedVTablePtr2 trivially_relocatable_if_eligible { + virtual ~RelocatableNonAddressDiscriminatedVTablePtr2(); + void *j; +}; + +struct AddressDiscriminatedVTablePtrAttr AddressDiscriminatedVTablePtr { + virtual ~AddressDiscriminatedVTablePtr(); + void *k; +}; + +struct AddressDiscriminatedVTablePtrAttr RelocatableAddressDiscriminatedVTablePtr trivially_relocatable_if_eligible { + virtual ~RelocatableAddressDiscriminatedVTablePtr(); + void *k; +}; + +struct NoAddressDiscriminatedBaseClasses : NonAddressDiscriminatedVTablePtr, + NonAddressDiscriminatedVTablePtr2 { + void *l; +}; + +struct RelocatableNoAddressDiscriminatedBaseClasses trivially_relocatable_if_eligible : + NonAddressDiscriminatedVTablePtr, + NonAddressDiscriminatedVTablePtr2 { + void *l; +}; + +struct AddressDiscriminatedPrimaryBase : AddressDiscriminatedVTablePtr, + NonAddressDiscriminatedVTablePtr { + void *l; +}; +struct AddressDiscriminatedSecondaryBase : NonAddressDiscriminatedVTablePtr, + AddressDiscriminatedVTablePtr { + void *l; +}; + +struct RelocatableAddressDiscriminatedPrimaryBase : RelocatableAddressDiscriminatedVTablePtr, + RelocatableNonAddressDiscriminatedVTablePtr { + void *l; +}; +struct RelocatableAddressDiscriminatedSecondaryBase : RelocatableNonAddressDiscriminatedVTablePtr, + RelocatableAddressDiscriminatedVTablePtr { + void *l; +}; +struct EmbdeddedAddressDiscriminatedPolymorphicClass { + AddressDiscriminatedVTablePtr field; +}; +struct RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass trivially_relocatable_if_eligible { + AddressDiscriminatedVTablePtr field; +}; + +static_assert( __is_pod(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_pod(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __is_pod(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_pod(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert(!__is_pod(AddressDiscriminatedFieldInBaseClass)); +static_assert(!__is_pod(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_pod(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_pod(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_pod(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_pod(AddressDiscriminatedVTablePtr)); +static_assert(!__is_pod(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_pod(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_pod(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_pod(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_pod(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_pod(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_pod(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_pod(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_pod(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_standard_layout(AddressDiscriminatedPtr)); +static_assert( __is_standard_layout(AddressDiscriminatedInt64)); +static_assert( __is_standard_layout(AddressDiscriminatedFields)); +static_assert( __is_standard_layout(RelocatableAddressDiscriminatedFields)); +static_assert(!__is_standard_layout(AddressDiscriminatedFieldInBaseClass)); +static_assert(!__is_standard_layout(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_standard_layout(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_standard_layout(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_standard_layout(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_standard_layout(AddressDiscriminatedVTablePtr)); +static_assert(!__is_standard_layout(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_standard_layout(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_standard_layout(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_standard_layout(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_standard_layout(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_standard_layout(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_standard_layout(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_standard_layout(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_standard_layout(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __has_trivial_move_constructor(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_constructor(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_constructor(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_constructor(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_constructor(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__has_trivial_move_constructor(NonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_constructor(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_move_constructor(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_constructor(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_move_constructor(AddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_constructor(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_constructor(NoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_move_constructor(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_move_constructor(AddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_move_constructor(AddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_move_constructor(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_move_constructor(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_move_constructor(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__has_trivial_move_constructor(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __has_trivial_copy(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_copy(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_copy(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_copy(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_copy(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__has_trivial_copy(NonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_copy(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_copy(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_copy(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_copy(AddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_copy(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_copy(NoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_copy(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_copy(AddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_copy(AddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_copy(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_copy(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_copy(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__has_trivial_copy(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __has_trivial_assign(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_assign(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_assign(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_assign(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_assign(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__has_trivial_assign(NonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_assign(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_assign(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_assign(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_assign(AddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_assign(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_assign(NoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_assign(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_assign(AddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_assign(AddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_assign(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_assign(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_assign(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__has_trivial_assign(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __has_trivial_move_assign(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_assign(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_assign(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_assign(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_trivial_move_assign(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__has_trivial_move_assign(NonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_assign(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_move_assign(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_assign(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_trivial_move_assign(AddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_assign(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__has_trivial_move_assign(NoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_move_assign(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__has_trivial_move_assign(AddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_move_assign(AddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_move_assign(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__has_trivial_move_assign(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__has_trivial_move_assign(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__has_trivial_move_assign(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_trivial(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_trivial(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __is_trivial(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivial(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivial(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__is_trivial(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivial(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivial(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivial(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivial(AddressDiscriminatedVTablePtr)); +static_assert(!__is_trivial(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivial(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivial(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivial(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivial(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivial(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivial(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivial(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_trivial(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_trivially_copyable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_copyable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_copyable(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_copyable(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_copyable(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__is_trivially_copyable(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_copyable(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_copyable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_copyable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_copyable(AddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_copyable(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_copyable(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_copyable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_copyable(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_copyable(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_copyable(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_copyable(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_copyable(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_trivially_copyable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_trivially_equality_comparable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_equality_comparable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert(!__is_trivially_equality_comparable(AddressDiscriminatedFields)); +static_assert(!__is_trivially_equality_comparable(RelocatableAddressDiscriminatedFields)); +static_assert(!__is_trivially_equality_comparable(AddressDiscriminatedFieldInBaseClass)); +static_assert(!__is_trivially_equality_comparable(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_equality_comparable(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_equality_comparable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_equality_comparable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_equality_comparable(AddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_equality_comparable(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_equality_comparable(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_equality_comparable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_equality_comparable(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_equality_comparable(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_equality_comparable(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_equality_comparable(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_equality_comparable(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_trivially_equality_comparable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_trivially_relocatable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_relocatable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_relocatable(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_relocatable(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_trivially_relocatable(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__is_trivially_relocatable(NonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_relocatable(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_relocatable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_relocatable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__is_trivially_relocatable(AddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_relocatable(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__is_trivially_relocatable(NoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_relocatable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__is_trivially_relocatable(AddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_relocatable(AddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_relocatable(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__is_trivially_relocatable(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__is_trivially_relocatable(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__is_trivially_relocatable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __builtin_is_cpp_trivially_relocatable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __builtin_is_cpp_trivially_relocatable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __builtin_is_cpp_trivially_relocatable(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __builtin_is_cpp_trivially_relocatable(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__builtin_is_cpp_trivially_relocatable(NonAddressDiscriminatedVTablePtr)); +static_assert(!__builtin_is_cpp_trivially_relocatable(NonAddressDiscriminatedVTablePtr2)); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__builtin_is_cpp_trivially_relocatable(AddressDiscriminatedVTablePtr)); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableAddressDiscriminatedVTablePtr) == !ADDR_DISC_ENABLED); +static_assert(!__builtin_is_cpp_trivially_relocatable(NoAddressDiscriminatedBaseClasses)); +static_assert(!__builtin_is_cpp_trivially_relocatable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__builtin_is_cpp_trivially_relocatable(AddressDiscriminatedPrimaryBase)); +static_assert(!__builtin_is_cpp_trivially_relocatable(AddressDiscriminatedSecondaryBase)); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableAddressDiscriminatedPrimaryBase) == !ADDR_DISC_ENABLED); +static_assert( __builtin_is_cpp_trivially_relocatable(RelocatableAddressDiscriminatedSecondaryBase) == !ADDR_DISC_ENABLED); +static_assert(!__builtin_is_cpp_trivially_relocatable(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__builtin_is_cpp_trivially_relocatable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __builtin_is_replaceable(AddressDiscriminatedPtr)); +static_assert( __builtin_is_replaceable(AddressDiscriminatedInt64)); +static_assert( __builtin_is_replaceable(AddressDiscriminatedFields)); +static_assert( __builtin_is_replaceable(RelocatableAddressDiscriminatedFields)); +static_assert( __builtin_is_replaceable(AddressDiscriminatedFieldInBaseClass)); +static_assert(!__builtin_is_replaceable(NonAddressDiscriminatedVTablePtr)); +static_assert(!__builtin_is_replaceable(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__builtin_is_replaceable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__builtin_is_replaceable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__builtin_is_replaceable(AddressDiscriminatedVTablePtr)); +static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__builtin_is_replaceable(NoAddressDiscriminatedBaseClasses)); +static_assert(!__builtin_is_replaceable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__builtin_is_replaceable(AddressDiscriminatedPrimaryBase)); +static_assert(!__builtin_is_replaceable(AddressDiscriminatedSecondaryBase)); +static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__builtin_is_replaceable(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__builtin_is_replaceable(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__builtin_is_replaceable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +static_assert( __is_bitwise_cloneable(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(NonAddressDiscriminatedVTablePtr)); +static_assert( __is_bitwise_cloneable(NonAddressDiscriminatedVTablePtr2)); +static_assert( __is_bitwise_cloneable(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert( __is_bitwise_cloneable(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedVTablePtr) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(RelocatableAddressDiscriminatedVTablePtr) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(NoAddressDiscriminatedBaseClasses)); +static_assert( __is_bitwise_cloneable(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedPrimaryBase) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(AddressDiscriminatedSecondaryBase) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(RelocatableAddressDiscriminatedPrimaryBase) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(RelocatableAddressDiscriminatedSecondaryBase) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(EmbdeddedAddressDiscriminatedPolymorphicClass) == !ADDR_DISC_ENABLED); +static_assert( __is_bitwise_cloneable(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass) == !ADDR_DISC_ENABLED); + +static_assert( __has_unique_object_representations(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( __has_unique_object_representations(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( __has_unique_object_representations(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_unique_object_representations(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( __has_unique_object_representations(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!__has_unique_object_representations(NonAddressDiscriminatedVTablePtr)); +static_assert(!__has_unique_object_representations(NonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_unique_object_representations(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!__has_unique_object_representations(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!__has_unique_object_representations(AddressDiscriminatedVTablePtr)); +static_assert(!__has_unique_object_representations(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!__has_unique_object_representations(NoAddressDiscriminatedBaseClasses)); +static_assert(!__has_unique_object_representations(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!__has_unique_object_representations(AddressDiscriminatedPrimaryBase)); +static_assert(!__has_unique_object_representations(AddressDiscriminatedSecondaryBase)); +static_assert(!__has_unique_object_representations(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!__has_unique_object_representations(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!__has_unique_object_representations(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!__has_unique_object_representations(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +#define ASSIGNABLE_WRAPPER(Type) __is_trivially_assignable(Type&, Type) +static_assert( ASSIGNABLE_WRAPPER(AddressDiscriminatedPtr) == !ADDR_DISC_ENABLED); +static_assert( ASSIGNABLE_WRAPPER(AddressDiscriminatedInt64) == !ADDR_DISC_ENABLED); +static_assert( ASSIGNABLE_WRAPPER(AddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( ASSIGNABLE_WRAPPER(RelocatableAddressDiscriminatedFields) == !ADDR_DISC_ENABLED); +static_assert( ASSIGNABLE_WRAPPER(AddressDiscriminatedFieldInBaseClass) == !ADDR_DISC_ENABLED); +static_assert(!ASSIGNABLE_WRAPPER(NonAddressDiscriminatedVTablePtr)); +static_assert(!ASSIGNABLE_WRAPPER(NonAddressDiscriminatedVTablePtr2)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableNonAddressDiscriminatedVTablePtr)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableNonAddressDiscriminatedVTablePtr2)); +static_assert(!ASSIGNABLE_WRAPPER(AddressDiscriminatedVTablePtr)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableAddressDiscriminatedVTablePtr)); +static_assert(!ASSIGNABLE_WRAPPER(NoAddressDiscriminatedBaseClasses)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableNoAddressDiscriminatedBaseClasses)); +static_assert(!ASSIGNABLE_WRAPPER(AddressDiscriminatedPrimaryBase)); +static_assert(!ASSIGNABLE_WRAPPER(AddressDiscriminatedSecondaryBase)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableAddressDiscriminatedPrimaryBase)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableAddressDiscriminatedSecondaryBase)); +static_assert(!ASSIGNABLE_WRAPPER(EmbdeddedAddressDiscriminatedPolymorphicClass)); +static_assert(!ASSIGNABLE_WRAPPER(RelocatableEmbdeddedAddressDiscriminatedPolymorphicClass)); + +namespace GH159505 { + class A { + virtual void f(); + }; + + template struct B { + class C : A { + A a[N]; + } d; + }; + + template struct C { + void *__ptrauth(1,1,1) ptr[N]; + static_assert(PTRAUTH_ENABLED != __is_trivially_copyable(decltype(ptr))); + }; + template struct D { + T ptr; + static_assert(isPtrauth != __is_trivially_copyable(decltype(ptr))); + }; + + + template using Ptr = T * __ptrauth(1,1,1); + template void test() { + static_assert(PTRAUTH_ENABLED != __is_trivially_copyable(Ptr)); + } + + auto f = test; + static_assert(!__is_trivially_copyable(B<1>)); + static_assert(PTRAUTH_ENABLED != __is_trivially_copyable(C<1>)); + + + D d_void; + D d_void_ptrauth; +} diff --git a/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp index b38499a634fcf..4a907b8c1cb5e 100644 --- a/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp +++ b/clang/test/SemaCXX/trivially-relocatable-ptrauth.cpp @@ -57,7 +57,7 @@ struct Foo : Polymorphic { }; -static_assert(__builtin_is_cpp_trivially_relocatable(Polymorphic)); +static_assert(!__builtin_is_cpp_trivially_relocatable(Polymorphic)); struct [[clang::ptrauth_vtable_pointer(process_independent,no_address_discrimination,no_extra_discrimination)]] NonAddressDiscriminatedPolymorphic trivially_relocatable_if_eligible { virtual ~NonAddressDiscriminatedPolymorphic(); @@ -70,7 +70,7 @@ struct PolymorphicMembers { Polymorphic field; }; -static_assert(__builtin_is_cpp_trivially_relocatable(PolymorphicMembers)); +static_assert(!__builtin_is_cpp_trivially_relocatable(PolymorphicMembers)); struct UnionOfPolymorphic { union trivially_relocatable_if_eligible { diff --git a/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp b/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp index fcff006d0e028..f17f20ca25295 100644 --- a/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp +++ b/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp @@ -14,7 +14,7 @@ void test(char8_t u8, char16_t u16, char32_t u32) { c16(u32); // expected-warning {{implicit conversion from 'char32_t' to 'char16_t' may lose precision and change the meaning of the represented code unit}} c32(u8); // expected-warning {{implicit conversion from 'char8_t' to 'char32_t' may change the meaning of the represented code unit}} - c32(u16); // expected-warning {{implicit conversion from 'char16_t' to 'char32_t' may change the meaning of the represented code unit}} + c32(u16); c32(u32); @@ -30,7 +30,7 @@ void test(char8_t u8, char16_t u16, char32_t u32) { c16(char32_t(0x7f)); c16(char32_t(0x80)); c16(char32_t(0xD7FF)); - c16(char32_t(0xD800)); // expected-warning {{implicit conversion from 'char32_t' to 'char16_t' changes the meaning of the code unit '<0xD800>'}} + c16(char32_t(0xD800)); c16(char32_t(0xE000)); c16(char32_t(U'🐉')); // expected-warning {{implicit conversion from 'char32_t' to 'char16_t' changes the meaning of the code point '🐉'}} @@ -44,8 +44,8 @@ void test(char8_t u8, char16_t u16, char32_t u32) { c32(char16_t(0x80)); c32(char16_t(0xD7FF)); - c32(char16_t(0xD800)); // expected-warning {{implicit conversion from 'char16_t' to 'char32_t' changes the meaning of the code unit '<0xD800>'}} - c32(char16_t(0xDFFF)); // expected-warning {{implicit conversion from 'char16_t' to 'char32_t' changes the meaning of the code unit '<0xDFFF>'}} + c32(char16_t(0xD800)); + c32(char16_t(0xDFFF)); c32(char16_t(0xE000)); c32(char16_t(u'☕')); diff --git a/clang/test/SemaCXX/warn-thread-safety-negative.cpp b/clang/test/SemaCXX/warn-thread-safety-negative.cpp index 9eabd67e4fc76..0caf6d6139e58 100644 --- a/clang/test/SemaCXX/warn-thread-safety-negative.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-negative.cpp @@ -21,6 +21,15 @@ class LOCKABLE Mutex { void AssertReaderHeld() ASSERT_SHARED_LOCK(); }; +class LOCKABLE REENTRANT_CAPABILITY ReentrantMutex { +public: + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + void Unlock() UNLOCK_FUNCTION(); + + // for negative capabilities + const ReentrantMutex& operator!() const { return *this; } +}; + class SCOPED_LOCKABLE MutexLock { public: MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu); @@ -89,6 +98,29 @@ class Foo { } }; +class Reentrant { + ReentrantMutex mu; + +public: + void acquire() { + mu.Lock(); // no warning -- reentrant mutex + mu.Unlock(); + } + + void requireNegative() EXCLUSIVE_LOCKS_REQUIRED(!mu) { // warning? + mu.Lock(); + mu.Unlock(); + } + + void callRequireNegative() { + requireNegative(); // expected-warning{{calling function 'requireNegative' requires negative capability '!mu'}} + } + + void callHaveNegative() EXCLUSIVE_LOCKS_REQUIRED(!mu) { + requireNegative(); + } +}; + } // end namespace SimpleTest Mutex globalMutex; diff --git a/clang/test/SemaCXX/wreturn-always-throws.cpp b/clang/test/SemaCXX/wreturn-always-throws.cpp index addcadd1183dc..df7689f7063cc 100644 --- a/clang/test/SemaCXX/wreturn-always-throws.cpp +++ b/clang/test/SemaCXX/wreturn-always-throws.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -verify %s +// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -Winvalid-noreturn -verify %s // expected-no-diagnostics namespace std { @@ -44,3 +44,22 @@ void testTemplates() { throwErrorTemplate("ERROR"); (void)ensureZeroTemplate(42); } + +// Ensure that explicit specialization of a member function does not inherit +// the warning from the primary template. + +template +struct S { + void f(); + void g(); +}; + +template +void S::f() { throw 0; } +template<> +void S::f() {} + +template +void S::g() {} +template<> +void S::g() { throw 0; } diff --git a/clang/test/SemaObjC/ptrauth-qualifier.m b/clang/test/SemaObjC/ptrauth-qualifier.m index 74bbe6f09899b..67a73bbe45777 100644 --- a/clang/test/SemaObjC/ptrauth-qualifier.m +++ b/clang/test/SemaObjC/ptrauth-qualifier.m @@ -1,13 +1,25 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios -fsyntax-only -verify -fptrauth-intrinsics %s +// RUN: %clang_cc1 -triple arm64-apple-ios -DIS_DARWIN -fsyntax-only -verify -fptrauth-intrinsics %s // RUN: %clang_cc1 -triple aarch64-linux-gnu -fsyntax-only -verify -fptrauth-intrinsics %s -#if !__has_extension(ptrauth_qualifier) +#if defined(IS_DARWIN) && !__has_extension(ptrauth_qualifier) // This error means that the __ptrauth qualifier availability test says that it // is not available. This error is not expected in the output, if it is seen // there is a feature detection regression. #error __ptrauth qualifier not enabled #endif +#if defined(IS_DARWIN) && !__has_feature(ptrauth_qualifier) +// This error means that the __has_feature test for ptrauth_qualifier has +// failed, despite it being expected on darwin. +#error __ptrauth qualifier not enabled +#elif !defined(IS_DARWIN) && (__has_feature(ptrauth_qualifier) || __has_extension(ptrauth_qualifier)) +#error ptrauth_qualifier labeled a feature on a non-darwin platform +#endif + +#if !defined (__PTRAUTH__) +#error __PTRAUTH__ test macro not defined when ptrauth is enabled +#endif + @interface Foo // expected-warning@-1 {{class 'Foo' defined without specifying a base class}} // expected-note@-2 {{add a super class to fix this problem}} diff --git a/clang/test/SemaObjCXX/discarded-block-type-inference.mm b/clang/test/SemaObjCXX/discarded-block-type-inference.mm new file mode 100644 index 0000000000000..8e2587724a7f6 --- /dev/null +++ b/clang/test/SemaObjCXX/discarded-block-type-inference.mm @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fobjc-arc -fblocks %s + +void block_receiver(int (^)() ); + +int f1() { + if constexpr (0) + (block_receiver)(^{ return 2; }); + return 1; +} + +int f2() { + if constexpr (0) + return (^{ return 2; })(); + return 1; +} diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 62a4f95d79c74..6d6052791507d 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1228,25 +1228,25 @@ template struct KnownType { } -namespace GH115838 { +namespace CWG2369_Regression_2 { -template concept has_x = requires(T t) {{ t.x };}; - -class Publ { public: int x = 0; }; -class Priv { private: int x = 0; }; -class Prot { protected: int x = 0; }; -class Same { protected: int x = 0; }; - -template class D; -template requires ( has_x) class D: public T { public: static constexpr bool has = 1; }; -template requires (!has_x) class D: public T { public: static constexpr bool has = 0; }; +template +concept HasFastPropertyForAttribute = + requires(T element, int name) { element.propertyForAttribute(name); }; + +template +struct SVGPropertyOwnerRegistry { + static int fastAnimatedPropertyLookup() { + static_assert (HasFastPropertyForAttribute); + return 1; + } +}; -// "Same" is identical to "Prot" but queried before used. -static_assert(!has_x, "Protected should be invisible."); -static_assert(!D::has, "Protected should be invisible."); +class SVGCircleElement { + friend SVGPropertyOwnerRegistry; + void propertyForAttribute(int); +}; -static_assert( D::has, "Public should be visible."); -static_assert(!D::has, "Private should be invisible."); -static_assert(!D::has, "Protected should be invisible."); +int i = SVGPropertyOwnerRegistry::fastAnimatedPropertyLookup(); } diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 0953f647426fa..f6bc6ee3673c2 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -966,3 +966,19 @@ Expand> _{}; // CHECK-NEXT: | `-ParmVarDecl {{.+}} 'T...' pack } + +namespace GH134613 { +template struct Foo { + using value_type = R; + + Foo() = default; + Foo(Foo> &&rhs) {} +}; + +void main() { + auto r1 = Foo(Foo>{}); + + static_assert(__is_same(decltype(r1)::value_type, int)); +} + +} diff --git a/clang/test/SemaTemplate/destructor-template.cpp b/clang/test/SemaTemplate/destructor-template.cpp index 7a3398308bbee..734269e854e5d 100644 --- a/clang/test/SemaTemplate/destructor-template.cpp +++ b/clang/test/SemaTemplate/destructor-template.cpp @@ -104,3 +104,18 @@ struct T : S { ~T() = default; }; } // namespace PR38671 + +namespace GH159630 { + +struct X { + template + struct typo { // expected-note {{'typo' declared here}} + ~typo(); + }; +}; + +template +X::typo::typ0::~typ0() {} // expected-error {{no member named 'typ0'}} \ + // expected-error {{no type named 'typ0'}} + +} diff --git a/clang/test/bindings/python/bindings.sh b/clang/test/bindings/python/bindings.sh deleted file mode 100755 index 3f7a51ef9ca49..0000000000000 --- a/clang/test/bindings/python/bindings.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# UNSUPPORTED: !libclang-loadable - -# Tests fail on Windows, and need someone knowledgeable to fix. -# It's not clear whether it's a test or a valid binding problem. -# XFAIL: target={{.*windows.*}} - -# The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628. -# XFAIL: target={{.*-aix.*}} - -# Hexagon has known test failures that need to be addressed. -# https://reviews.llvm.org/D52840#1265716 -# XFAIL: target={{hexagon-.*}} -# python SEGVs on Linux/sparc64 when loading libclang.so. Seems to be an FFI -# issue, too. -# XFAIL: target={{sparc.*-.*-linux.*}} - -# Tests will fail if cross-compiling for a different target, as tests will try -# to use the host Python3_EXECUTABLE and make FFI calls to functions in target -# libraries. -# -# FIXME: Consider a solution that allows better control over these tests in -# a crosscompiling scenario. e.g. registering them with lit to allow them to -# be explicitly skipped via appropriate LIT_ARGS, or adding a mechanism to -# allow specifying a python interpreter compiled for the target that could -# be executed using qemu-user. -# REQUIRES: native - -# SystemZ has broken Python/FFI interface -# according to https://reviews.llvm.org/D52840#1265716 -# This leads to failures only when Clang is built with GCC apparently, see: -# https://github.com/llvm/llvm-project/pull/146844#issuecomment-3048291798 -# REQUIRES: !target={{s390x-.*}} - -# RUN: env PYTHONPATH=%S/../../../bindings/python \ -# RUN: CLANG_LIBRARY_PATH=%libdir \ -# RUN: %python -m unittest discover -s %S/tests diff --git a/clang/test/bindings/python/lit.local.cfg b/clang/test/bindings/python/lit.local.cfg deleted file mode 100644 index cc3bdf8ba97d4..0000000000000 --- a/clang/test/bindings/python/lit.local.cfg +++ /dev/null @@ -1,41 +0,0 @@ -def is_libclang_loadable(): - # Do not try to run if libclang was built with sanitizers because - # the sanitizer library will likely be loaded too late to perform - # interception and will then fail. - # We could use LD_PRELOAD/DYLD_INSERT_LIBRARIES but this isn't - # portable so its easier just to not run the tests when building - # with ASan. - if config.llvm_use_sanitizer != "": - return False - try: - sys.path.append(os.path.join(config.clang_src_dir, "bindings/python")) - from clang.cindex import Config - conf = Config() - Config.set_library_path(config.clang_lib_dir) - conf.lib - return True - except Exception as e: - # Expected failure modes are considered benign when nothing can be - # done about them. - # - # Cannot load a 32-bit libclang.so into a 64-bit python. - if "wrong ELF class: ELFCLASS32" in str(e): - return False - # If libclang.so is missing, it must have been disabled intentionally, - # e.g. by building with LLVM_ENABLE_PIC=OFF. - elif "No such file or directory" in str(e): - return False - # Unexpected failure modes need to be investigated to either fix an - # underlying bug or accept the failure, so return True. This causes - # tests to run and FAIL, drawing developer attention. - else: - print("warning: unhandled failure in is_libclang_loadable: " - + str(e), file=sys.stderr) - return True - -if is_libclang_loadable(): - config.available_features.add("libclang-loadable") - -config.substitutions.append(('%libdir', config.clang_lib_dir)) - -config.suffixes = ['.sh'] diff --git a/clang/tools/clang-format/git-clang-format b/clang/tools/clang-format/git-clang-format index e709803d9a3f1..fe2dd283d403e 100755 --- a/clang/tools/clang-format/git-clang-format +++ b/clang/tools/clang-format/git-clang-format @@ -419,7 +419,7 @@ def compute_diff(commits, files, staged, diff_common_commit): if len(commits) == 2: git_tool = "diff-tree" if diff_common_commit: - commits = [f"{commits[0]}...{commits[1]}"] + extra_args += ["--merge-base"] elif staged: extra_args += ["--cached"] diff --git a/clang/tools/clang-shlib/CMakeLists.txt b/clang/tools/clang-shlib/CMakeLists.txt index 945076e1ad810..a4d0aa5779a7e 100644 --- a/clang/tools/clang-shlib/CMakeLists.txt +++ b/clang/tools/clang-shlib/CMakeLists.txt @@ -41,6 +41,10 @@ if (CLANG_LINK_CLANG_DYLIB) set(INSTALL_WITH_TOOLCHAIN INSTALL_WITH_TOOLCHAIN) endif() +if (HAIKU) + list(APPEND _DEPS network) +endif() + add_clang_library(clang-cpp SHARED ${INSTALL_WITH_TOOLCHAIN} diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index b6662b66206b2..2b1e266f07392 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCES Indexing.cpp FatalErrorHandler.cpp Rewrite.cpp + Obsolete.cpp ADDITIONAL_HEADERS CIndexDiagnostic.h diff --git a/clang/tools/libclang/Obsolete.cpp b/clang/tools/libclang/Obsolete.cpp new file mode 100644 index 0000000000000..3596f76e1be6f --- /dev/null +++ b/clang/tools/libclang/Obsolete.cpp @@ -0,0 +1,48 @@ +//===- Obsolete.cpp - Obsolete libclang functions and types -------------===// +// +// 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 contains libclang symbols whose underlying functionality has been +// removed from Clang, but which need to be kept around so as to retain ABI +// compatibility. +// +//===--------------------------------------------------------------------===// + +#include "clang-c/CXString.h" +#include "clang-c/Index.h" +#include "clang-c/Platform.h" +#include "llvm/Support/raw_ostream.h" + +extern "C" { + +// The functions below used to be part of the C API for ARCMigrate, which has +// since been removed from Clang; they already used to print an error if Clang +// was compiled without arcmt support, so we continue doing so. +CXRemapping clang_getRemappings(const char *) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return nullptr; +} + +CXRemapping clang_getRemappingsFromFileList(const char **, unsigned) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return nullptr; +} + +unsigned clang_remap_getNumFiles(CXRemapping) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; + return 0; +} + +void clang_remap_getFilenames(CXRemapping, unsigned, CXString *, CXString *) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; +} + +void clang_remap_dispose(CXRemapping) { + llvm::errs() << "error: ARCMigrate has been removed from Clang"; +} + +} // extern "C" diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map index d140a71e771a0..3d9d2e268a611 100644 --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -327,6 +327,8 @@ LLVM_13 { clang_getRange; clang_getRangeEnd; clang_getRangeStart; + clang_getRemappings; + clang_getRemappingsFromFileList; clang_getResultType; clang_getSkippedRanges; clang_getSpecializedCursorTemplate; @@ -387,6 +389,9 @@ LLVM_13 { clang_parseTranslationUnit; clang_parseTranslationUnit2; clang_parseTranslationUnit2FullArgv; + clang_remap_dispose; + clang_remap_getFilenames; + clang_remap_getNumFiles; clang_reparseTranslationUnit; clang_saveTranslationUnit; clang_sortCodeCompletionResults; @@ -435,12 +440,12 @@ LLVM_20 { clang_getTypePrettyPrinted; clang_isBeforeInTranslationUnit; clang_visitCXXBaseClasses; - clang_visitCXXMethods; }; LLVM_21 { global: clang_getFullyQualifiedName; + clang_visitCXXMethods; clang_Cursor_getGCCAssemblyTemplate; clang_Cursor_isGCCAssemblyHasGoto; clang_Cursor_getGCCAssemblyNumOutputs; diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index d17109aebc0f8..ff42f09b90cf3 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -249,6 +249,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterFunctionDefinitionName); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterIfMacros); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterNot); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterPlacementOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses); @@ -1248,6 +1249,13 @@ TEST(ConfigParseTest, ParsesConfigurationWithLanguages) { IndentWidth, 56u); } +TEST(ConfigParseTest, AllowCommentOnlyConfigFile) { + FormatStyle Style = {}; + Style.Language = FormatStyle::LK_Cpp; + EXPECT_EQ(parseConfiguration("#Language: C", &Style), ParseError::Success); + EXPECT_EQ(Style.Language, FormatStyle::LK_Cpp); +} + TEST(ConfigParseTest, AllowCppForC) { FormatStyle Style = {}; Style.Language = FormatStyle::LK_C; @@ -1268,7 +1276,7 @@ TEST(ConfigParseTest, AllowCppForC) { ParseError::Success); } -TEST(ConfigParseTest, HandleNonCppDotHFile) { +TEST(ConfigParseTest, HandleDotHFile) { FormatStyle Style = {}; Style.Language = FormatStyle::LK_Cpp; EXPECT_EQ(parseConfiguration("Language: C", &Style, @@ -1279,11 +1287,14 @@ TEST(ConfigParseTest, HandleNonCppDotHFile) { Style = {}; Style.Language = FormatStyle::LK_Cpp; - EXPECT_EQ(parseConfiguration("Language: ObjC", &Style, + EXPECT_EQ(parseConfiguration("Language: Cpp\n" + "...\n" + "Language: C", + &Style, /*AllowUnknownOptions=*/false, /*IsDotHFile=*/true), ParseError::Success); - EXPECT_EQ(Style.Language, FormatStyle::LK_ObjC); + EXPECT_EQ(Style.Language, FormatStyle::LK_Cpp); } TEST(ConfigParseTest, UsesLanguageForBasedOnStyle) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 0bc1c6d45656e..760c5a4ce4195 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1364,6 +1364,27 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) { AllowsMergedIf); } +TEST_F(FormatTest, WrapMultipleStatementIfAndElseBraces) { + auto Style = getLLVMStyle(); + Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; + Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_AllIfsAndElse; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; + Style.BraceWrapping.BeforeElse = true; + + verifyFormat("if (x)\n" + "{\n" + " ++x;\n" + " --y;\n" + "}\n" + "else\n" + "{\n" + " --x;\n" + " ++y;\n" + "}", + Style); +} + TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) { verifyFormat("while (true)\n" " ;"); @@ -4050,6 +4071,10 @@ TEST_F(FormatTest, FormatsBitfields) { " uchar : 8;\n" " uchar other;\n" "};"); + verifyFormat("struct foo {\n" + " uint8_t i_am_a_bit_field_this_long\n" + " : struct_with_constexpr::i_am_a_constexpr_lengthhhhh;\n" + "};"); FormatStyle Style = getLLVMStyle(); Style.BitFieldColonSpacing = FormatStyle::BFCS_None; verifyFormat("struct Bitfields {\n" @@ -8571,10 +8596,10 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { "operator<<(const SomeLooooooooooooooooooooooooogType &other);"); verifyGoogleFormat( "SomeLoooooooooooooooooooooooooooooogType operator>>(\n" - " const SomeLooooooooogType &a, const SomeLooooooooogType &b);"); + " const SomeLooooooooogType& a, const SomeLooooooooogType& b);"); verifyGoogleFormat( "SomeLoooooooooooooooooooooooooooooogType operator<<(\n" - " const SomeLooooooooogType &a, const SomeLooooooooogType &b);"); + " const SomeLooooooooogType& a, const SomeLooooooooogType& b);"); verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 1);"); @@ -8583,7 +8608,7 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { verifyGoogleFormat( "typename aaaaaaaaaa::aaaaaaaaaaa\n" "aaaaaaaaaa::aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" - " bool *aaaaaaaaaaaaaaaaaa, bool *aa) {}"); + " bool* aaaaaaaaaaaaaaaaaa, bool* aa) {}"); verifyGoogleFormat("template \n" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" "aaaaaaaaaaaaaaaaaaaaaaa::aaaaaaaaaaaaa(\n" @@ -8592,7 +8617,7 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { verifyFormat("extern \"C\" //\n" " void f();"); - FormatStyle Style = getLLVMStyle(); + auto Style = getLLVMStyle(); Style.PointerAlignment = FormatStyle::PAS_Left; verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaaaaaaaaa* const aaaaaaaaaaaa) {}", @@ -8600,6 +8625,14 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { verifyFormat("void aaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}", Style); + + Style = getLLVMStyleWithColumns(45); + Style.PenaltyReturnTypeOnItsOwnLine = 400; + verifyFormat("template \n" + "static inline std::pair\n" + "myfunc(const char *buf, const char *&err);", + Style); } TEST_F(FormatTest, DontBreakBeforeQualifiedOperator) { @@ -9694,6 +9727,19 @@ TEST_F(FormatTest, ParenthesesAndOperandAlignment) { Style); } +TEST_F(FormatTest, BlockIndentAndNamespace) { + auto Style = getLLVMStyleWithColumns(120); + Style.AllowShortNamespacesOnASingleLine = true; + Style.AlignAfterOpenBracket = FormatStyle::BAS_BlockIndent; + + verifyNoCrash( + "namespace {\n" + "void xxxxxxxxxxxxxxxxxxxxx(nnnnn::TTTTTTTTTTTTT const *mmmm,\n" + " YYYYYYYYYYYYYYYYY &yyyyyyyyyyyyyy);\n" + "} //", + Style); +} + TEST_F(FormatTest, BreaksConditionalExpressions) { verifyFormat( "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa\n" @@ -12891,27 +12937,31 @@ TEST_F(FormatTest, UnderstandsEllipsis) { } TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) { + auto Style = getGoogleStyle(); + EXPECT_FALSE(Style.DerivePointerAlignment); + Style.DerivePointerAlignment = true; + verifyFormat("int *a;\n" "int *a;\n" "int *a;", "int *a;\n" "int* a;\n" "int *a;", - getGoogleStyle()); + Style); verifyFormat("int* a;\n" "int* a;\n" "int* a;", "int* a;\n" "int* a;\n" "int *a;", - getGoogleStyle()); + Style); verifyFormat("int *a;\n" "int *a;\n" "int *a;", "int *a;\n" "int * a;\n" "int * a;", - getGoogleStyle()); + Style); verifyFormat("auto x = [] {\n" " int *a;\n" " int *a;\n" @@ -12920,7 +12970,7 @@ TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) { "auto x=[]{int *a;\n" "int * a;\n" "int * a;};", - getGoogleStyle()); + Style); } TEST_F(FormatTest, UnderstandsRvalueReferences) { @@ -13056,7 +13106,7 @@ TEST_F(FormatTest, FormatsCasts) { verifyFormat("virtual void foo(char &) const;"); verifyFormat("virtual void foo(int *a, char *) const;"); verifyFormat("int a = sizeof(int *) + b;"); - verifyGoogleFormat("int a = alignof(int *) + b;"); + verifyGoogleFormat("int a = alignof(int*) + b;"); verifyFormat("bool b = f(g) && c;"); verifyFormat("typedef void (*f)(int i) func;"); verifyFormat("void operator++(int) noexcept;"); @@ -17652,6 +17702,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("int x = int (y);", SomeSpace2); verifyFormat("auto lambda = []() { return 0; };", SomeSpace2); + auto Style = getLLVMStyle(); + Style.SpaceBeforeParens = FormatStyle::SBPO_Custom; + EXPECT_FALSE(Style.SpaceBeforeParensOptions.AfterNot); + Style.SpaceBeforeParensOptions.AfterNot = true; + verifyFormat("return not (a || b);", Style); + FormatStyle SpaceAfterOverloadedOperator = getLLVMStyle(); SpaceAfterOverloadedOperator.SpaceBeforeParens = FormatStyle::SBPO_Custom; SpaceAfterOverloadedOperator.SpaceBeforeParensOptions @@ -22373,6 +22429,19 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) { "});", Style); + verifyNoCrash( + "PANEL_Ic PANEL_ic[PANEL_IC_NUMBER] =\n" + " {\n" + " {PIC(0), PIC(0), PIC(99), PIC(81), 0}, // Backbox\n" + " {PIC(1), PIC(83), PIC(191), PIC(137), 0}, // AK47\n" + "\n" + "#define PICALL1(a, b, c, d) \\\n" + " { PIC(a), PIC(b), PIC(c), PIC(d), 1 }\n" + "\n" + " PICALL1(1, 1, 75, 50),\n" + "};", + Style); + Style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define FOO \\\n" " int foo[][2] = { \\\n" @@ -25059,6 +25128,11 @@ TEST_F(FormatTest, OneLineFormatOffRegex) { " } while (0 )", Style); + Style.OneLineFormatOffRegex = "MACRO_TEST"; + verifyNoChange(" MACRO_TEST1 ( ) ;\n" + " MACRO_TEST2( );", + Style); + Style.ColumnLimit = 50; Style.OneLineFormatOffRegex = "^LogErrorPrint$"; verifyFormat(" myproject::LogErrorPrint(logger, \"Don't split me!\");\n" @@ -25419,7 +25493,7 @@ TEST_F(FormatTest, AtomicQualifier) { verifyFormat("struct foo {\n" " int a1;\n" " _Atomic(a) a2;\n" - " _Atomic(_Atomic(int) *const) a3;\n" + " _Atomic(_Atomic(int)* const) a3;\n" "};", Google); verifyFormat("_Atomic(uint64_t) a;"); diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp index b1e42e924e05c..67b9cc9037905 100644 --- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp +++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp @@ -83,6 +83,9 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) { "d = 5678_km;\n" "h = 0xDEF_u16;", Style); + + Style.Standard = FormatStyle::LS_Cpp11; + verifyFormat("ld = 1234L;", Style); } TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) { diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index f42f2e307f713..55bdda32453ba 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -215,6 +215,8 @@ TEST_F(QualifierFixerTest, RightQualifier) { Style); verifyFormat("void foo() const override;", Style); verifyFormat("void foo() const override LLVM_READONLY;", Style); + verifyFormat("MOCK_METHOD(ReturnType, myMethod, (int), (const override));", + Style); verifyFormat("void foo() const final;", Style); verifyFormat("void foo() const final LLVM_READONLY;", Style); verifyFormat("void foo() const LLVM_READONLY;", Style); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index e281a4945a862..810c716b7a411 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -390,6 +390,10 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace); EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator); + Tokens = annotate("bool foo = requires { static_cast(1); };"); + ASSERT_EQ(Tokens.size(), 17u) << Tokens; + EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_PointerOrReference); + Tokens = annotate("return s.operator int *();"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; // Not TT_FunctionDeclarationName. @@ -614,6 +618,13 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) { EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_StructLBrace); EXPECT_TOKEN(Tokens[20], tok::r_brace, TT_StructRBrace); + Tokens = annotate("class Outer {\n" + " struct Inner final : Base {};\n" + "};"); + ASSERT_EQ(Tokens.size(), 14u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::identifier, TT_Unknown); // Not TT_StartOfName + EXPECT_TOKEN(Tokens[6], tok::colon, TT_InheritanceColon); + constexpr StringRef Code{"struct EXPORT StructName {};"}; Tokens = annotate(Code); @@ -1118,6 +1129,11 @@ TEST_F(TokenAnnotatorTest, UnderstandsOverloadedOperators) { ASSERT_EQ(Tokens.size(), 7u) << Tokens; // Not TT_FunctionDeclarationName. EXPECT_TOKEN(Tokens[3], tok::kw_operator, TT_Unknown); + + Tokens = annotate("SomeAPI::operator()();"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + // Not TT_FunctionDeclarationName. + EXPECT_TOKEN(Tokens[2], tok::kw_operator, TT_Unknown); } TEST_F(TokenAnnotatorTest, OverloadedOperatorInTemplate) { @@ -1338,6 +1354,14 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { EXPECT_EQ(Tokens[21]->MatchingParen, Tokens[15]); EXPECT_TRUE(Tokens[21]->ClosesRequiresClause); + Tokens = annotate("template \n" + "void Fun(const Foo &F)\n" + " requires requires(Foo F) {\n" + " { F.Bar() } -> std::same_as;\n" + " };"); + ASSERT_EQ(Tokens.size(), 38u) << Tokens; + EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace); + Tokens = annotate("template concept C =" "std::same_as, std::iter_value_t>;"); @@ -2218,6 +2242,18 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 21u) << Tokens; EXPECT_TOKEN(Tokens[11], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("SomeFunction({[]() -> int *[] { return {}; }});"); + ASSERT_EQ(Tokens.size(), 22u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen); + EXPECT_TOKEN(Tokens[10], tok::l_square, TT_ArraySubscriptLSquare); + + Tokens = annotate("foo = bar * [] { return 2; }();"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::star, TT_BinaryOperator); + EXPECT_TOKEN(Tokens[4], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) { @@ -4086,6 +4122,13 @@ TEST_F(TokenAnnotatorTest, UTF8StringLiteral) { EXPECT_TOKEN(Tokens[1], tok::utf8_string_literal, TT_Unknown); } +TEST_F(TokenAnnotatorTest, C23DigitSeparator) { + auto Tokens = annotate("return 1'000;", getLLVMStyle(FormatStyle::LK_C)); + ASSERT_EQ(Tokens.size(), 4u) << Tokens; + EXPECT_EQ(Tokens[1]->TokenText, "1'000"); + EXPECT_TOKEN(Tokens[2], tok::semi, TT_Unknown); +} + TEST_F(TokenAnnotatorTest, IdentifierPackage) { auto Tokens = annotate("auto package;"); ASSERT_EQ(Tokens.size(), 4u) << Tokens; @@ -4133,6 +4176,14 @@ TEST_F(TokenAnnotatorTest, LineCommentTrailingBackslash) { EXPECT_TOKEN(Tokens[1], tok::comment, TT_LineComment); } +TEST_F(TokenAnnotatorTest, ArrowAfterSubscript) { + auto Tokens = + annotate("return (getStructType()->getElements())[eIdx]->getName();"); + ASSERT_EQ(Tokens.size(), 19u) << Tokens; + // Not TT_LambdaArrow. + EXPECT_TOKEN(Tokens[13], tok::arrow, TT_Unknown); +} + } // namespace } // namespace format } // namespace clang diff --git a/clang/unittests/Lex/CMakeLists.txt b/clang/unittests/Lex/CMakeLists.txt index 96ca6dda9cd85..fa5e58f5a8932 100644 --- a/clang/unittests/Lex/CMakeLists.txt +++ b/clang/unittests/Lex/CMakeLists.txt @@ -5,6 +5,7 @@ add_clang_unittest(LexTests LexerTest.cpp LexHLSLRootSignatureTest.cpp ModuleDeclStateTest.cpp + NoTrivialPPDirectiveTracerTest.cpp PPCallbacksTest.cpp PPConditionalDirectiveRecordTest.cpp PPDependencyDirectivesTest.cpp diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index 86df872f6b7df..bb6404c434485 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -796,7 +796,7 @@ TEST_F(LexerTest, CheckFirstPPToken) { EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, PP->getSourceManager(), PP->getLangOpts(), /*IgnoreWhiteSpace=*/false)); - EXPECT_TRUE(Tok.isFirstPPToken()); + EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); EXPECT_TRUE(Tok.is(tok::hash)); } @@ -812,7 +812,7 @@ TEST_F(LexerTest, CheckFirstPPToken) { EXPECT_FALSE(Lexer::getRawToken(PP->getMainFileFirstPPTokenLoc(), Tok, PP->getSourceManager(), PP->getLangOpts(), /*IgnoreWhiteSpace=*/false)); - EXPECT_TRUE(Tok.isFirstPPToken()); + EXPECT_TRUE(PP->getMainFileFirstPPTokenLoc() == Tok.getLocation()); EXPECT_TRUE(Tok.is(tok::raw_identifier)); EXPECT_TRUE(Tok.getRawIdentifier() == "FOO"); } diff --git a/clang/unittests/Lex/ModuleDeclStateTest.cpp b/clang/unittests/Lex/ModuleDeclStateTest.cpp index 6ecba4de3187c..0c03cfd6d0f89 100644 --- a/clang/unittests/Lex/ModuleDeclStateTest.cpp +++ b/clang/unittests/Lex/ModuleDeclStateTest.cpp @@ -61,14 +61,15 @@ class ModuleDeclStateTest : public ::testing::Test { Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); } - std::unique_ptr - getPreprocessor(const char *source, Language Lang) { + std::unique_ptr getPreprocessor(const char *source, + Language Lang) { std::unique_ptr Buf = llvm::MemoryBuffer::getMemBuffer(source); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); std::vector Includes; - LangOptions::setLangDefaults(LangOpts, Lang, Target->getTriple(), Includes, LangStandard::lang_cxx20); + LangOptions::setLangDefaults(LangOpts, Lang, Target->getTriple(), Includes, + LangStandard::lang_cxx20); LangOpts.CPlusPlusModules = true; if (Lang != Language::CXX) { LangOpts.Modules = true; @@ -113,12 +114,11 @@ export module foo; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_TRUE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -132,12 +132,11 @@ module foo; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_TRUE(PP->isInImplementationUnit()); @@ -151,12 +150,11 @@ module foo:part; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -170,12 +168,11 @@ export module foo:part; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_TRUE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -189,12 +186,11 @@ export module foo.dot:part.dot; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_TRUE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -208,12 +204,11 @@ TEST_F(ModuleDeclStateTest, NotModule) { std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)0); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0); EXPECT_FALSE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -234,12 +229,11 @@ import :another; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {true, true}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)2); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)2); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_TRUE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -261,12 +255,11 @@ import :another; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {true, true}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)2); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)2); EXPECT_TRUE(PP->isInNamedModule()); EXPECT_TRUE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -287,12 +280,11 @@ import :another; std::unique_ptr PP = getPreprocessor(source, Language::CXX); std::initializer_list ImportKinds = {true}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)1); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)1); EXPECT_FALSE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -305,12 +297,11 @@ TEST_F(ModuleDeclStateTest, ImportAClangNamedModule) { std::unique_ptr PP = getPreprocessor(source, Language::ObjCXX); std::initializer_list ImportKinds = {false}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)1); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)1); EXPECT_FALSE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); @@ -327,12 +318,11 @@ import M2; std::unique_ptr PP = getPreprocessor(source, Language::ObjCXX); std::initializer_list ImportKinds = {false, true, false, true}; - preprocess(*PP, - std::make_unique(*PP, ImportKinds)); - - auto *Callback = - static_cast(PP->getPPCallbacks()); - EXPECT_EQ(Callback->importNamedModuleNum(), (size_t)4); + auto Callback = + std::make_unique(*PP, ImportKinds); + CheckNamedModuleImportingCB *CallbackPtr = Callback.get(); + preprocess(*PP, std::move(Callback)); + EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)4); EXPECT_FALSE(PP->isInNamedModule()); EXPECT_FALSE(PP->isInNamedInterfaceUnit()); EXPECT_FALSE(PP->isInImplementationUnit()); diff --git a/clang/unittests/Lex/NoTrivialPPDirectiveTracerTest.cpp b/clang/unittests/Lex/NoTrivialPPDirectiveTracerTest.cpp new file mode 100644 index 0000000000000..8b546fe2a40e2 --- /dev/null +++ b/clang/unittests/Lex/NoTrivialPPDirectiveTracerTest.cpp @@ -0,0 +1,183 @@ +//===- unittests/Lex/NoTrivialPPDirectiveTracerTest.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/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "gtest/gtest.h" +#include +#include + +using namespace clang; + +namespace { +class NoTrivialPPDirectiveTracerTest : public ::testing::Test { +protected: + NoTrivialPPDirectiveTracerTest() + : VFS(llvm::makeIntrusiveRefCnt()), + FileMgr(FileMgrOpts, VFS), DiagID(new DiagnosticIDs()), + Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), + SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) { + TargetOpts->Triple = "x86_64-unknown-linux-gnu"; + Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts); + } + + void addFile(const char *source, StringRef Filename) { + VFS->addFile(Filename, 0, llvm::MemoryBuffer::getMemBuffer(source), + /*User=*/std::nullopt, + /*Group=*/std::nullopt, + llvm::sys::fs::file_type::regular_file); + } + + std::unique_ptr getPreprocessor(const char *source, + Language Lang) { + std::unique_ptr Buf = + llvm::MemoryBuffer::getMemBuffer(source); + SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf))); + + std::vector Includes; + LangOptions::setLangDefaults(LangOpts, Lang, Target->getTriple(), Includes, + LangStandard::lang_cxx20); + LangOpts.CPlusPlusModules = true; + if (Lang != Language::CXX) { + LangOpts.Modules = true; + LangOpts.ImplicitModules = true; + } + + HeaderInfo.emplace(HSOpts, SourceMgr, Diags, LangOpts, Target.get()); + + auto DE = FileMgr.getOptionalDirectoryRef("."); + assert(DE); + auto DL = DirectoryLookup(*DE, SrcMgr::C_User, /*isFramework=*/false); + HeaderInfo->AddSearchPath(DL, /*isAngled=*/false); + + return std::make_unique(PPOpts, Diags, LangOpts, SourceMgr, + *HeaderInfo, ModLoader, + /*IILookup=*/nullptr, + /*OwnsHeaderSearch=*/false); + } + + IntrusiveRefCntPtr VFS; + FileSystemOptions FileMgrOpts; + FileManager FileMgr; + IntrusiveRefCntPtr DiagID; + DiagnosticOptions DiagOpts; + DiagnosticsEngine Diags; + SourceManager SourceMgr; + std::shared_ptr TargetOpts; + IntrusiveRefCntPtr Target; + LangOptions LangOpts; + TrivialModuleLoader ModLoader; + HeaderSearchOptions HSOpts; + std::optional HeaderInfo; + PreprocessorOptions PPOpts; +}; + +TEST_F(NoTrivialPPDirectiveTracerTest, TrivialDirective) { + const char *source = R"( + #line 7 + # 1 __FILE__ 1 3 + #ident "$Header:$" + #pragma comment(lib, "msvcrt.lib") + #pragma mark LLVM's world + #pragma detect_mismatch("test", "1") + #pragma clang __debug dump Test + #pragma message "test" + #pragma GCC warning "Foo" + #pragma GCC error "Foo" + #pragma gcc diagnostic push + #pragma gcc diagnostic pop + #pragma GCC diagnostic ignored "-Wframe-larger-than" + #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable + #pragma warning(push) + #pragma warning(pop) + #pragma execution_character_set(push, "UTF-8") + #pragma execution_character_set(pop) + #pragma clang assume_nonnull begin + #pragma clang assume_nonnull end + int foo; + )"; + std::unique_ptr PP = getPreprocessor(source, Language::CXX); + PP->Initialize(*Target); + PP->EnterMainSourceFile(); + Token Tok; + PP->Lex(Tok); + EXPECT_FALSE(PP->hasSeenNoTrivialPPDirective()); +} + +TEST_F(NoTrivialPPDirectiveTracerTest, IncludeDirective) { + const char *source = R"( + #include "header.h" + int foo; + )"; + const char *header = R"( + #ifndef HEADER_H + #define HEADER_H + #endif // HEADER_H + )"; + std::unique_ptr PP = getPreprocessor(source, Language::CXX); + addFile(header, "header.h"); + PP->Initialize(*Target); + PP->EnterMainSourceFile(); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(PP->hasSeenNoTrivialPPDirective()); +} + +TEST_F(NoTrivialPPDirectiveTracerTest, DefineDirective) { + const char *source = R"( + #define FOO + int foo; + )"; + std::unique_ptr PP = getPreprocessor(source, Language::CXX); + PP->Initialize(*Target); + PP->EnterMainSourceFile(); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(PP->hasSeenNoTrivialPPDirective()); +} + +TEST_F(NoTrivialPPDirectiveTracerTest, UnDefineDirective) { + const char *source = R"( + #undef FOO + int foo; + )"; + std::unique_ptr PP = getPreprocessor(source, Language::CXX); + PP->Initialize(*Target); + PP->setPredefines("#define FOO"); + PP->EnterMainSourceFile(); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(PP->hasSeenNoTrivialPPDirective()); +} + +TEST_F(NoTrivialPPDirectiveTracerTest, IfDefinedDirective) { + const char *source = R"( + #if defined(FOO) + #endif + int foo; + )"; + std::unique_ptr PP = getPreprocessor(source, Language::CXX); + PP->Initialize(*Target); + PP->setPredefines("#define FOO"); + PP->EnterMainSourceFile(); + Token Tok; + PP->Lex(Tok); + EXPECT_TRUE(PP->hasSeenNoTrivialPPDirective()); +} + +} // namespace diff --git a/cmake/Modules/CMakePolicy.cmake b/cmake/Modules/CMakePolicy.cmake index 421f5a4dda6c6..cf986331707b6 100644 --- a/cmake/Modules/CMakePolicy.cmake +++ b/cmake/Modules/CMakePolicy.cmake @@ -41,3 +41,9 @@ if(POLICY CMP0156) cmake_policy(SET CMP0179 NEW) endif() endif() + +# CMP0182: Create shared library archives by default on AIX. +# New in CMake 4.0: https://cmake.org/cmake/help/latest/policy/CMP0182.html +if(POLICY CMP0182) + cmake_policy(SET CMP0182 NEW) +endif() diff --git a/cmake/Modules/LLVMVersion.cmake b/cmake/Modules/LLVMVersion.cmake index f14aae172f077..908d52f238128 100644 --- a/cmake/Modules/LLVMVersion.cmake +++ b/cmake/Modules/LLVMVersion.cmake @@ -4,12 +4,12 @@ if(NOT DEFINED LLVM_VERSION_MAJOR) set(LLVM_VERSION_MAJOR 21) endif() if(NOT DEFINED LLVM_VERSION_MINOR) - set(LLVM_VERSION_MINOR 0) + set(LLVM_VERSION_MINOR 1) endif() if(NOT DEFINED LLVM_VERSION_PATCH) - set(LLVM_VERSION_PATCH 0) + set(LLVM_VERSION_PATCH 8) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX git) + set(LLVM_VERSION_SUFFIX) endif() diff --git a/compiler-rt/lib/builtins/aarch64/lse.S b/compiler-rt/lib/builtins/aarch64/lse.S index d7c1db7243ef8..a444d82892c36 100644 --- a/compiler-rt/lib/builtins/aarch64/lse.S +++ b/compiler-rt/lib/builtins/aarch64/lse.S @@ -264,7 +264,7 @@ END_COMPILERRT_OUTLINE_FUNCTION(NAME(LDNM)) NO_EXEC_STACK_DIRECTIVE -// GNU property note for BTI and PAC -GNU_PROPERTY_BTI_PAC +// GNU property note for BTI, PAC, and GCS +GNU_PROPERTY_BTI_PAC_GCS #endif // defined(__aarch64__) || defined(__arm64ec__) diff --git a/compiler-rt/lib/builtins/aarch64/sme-abi.S b/compiler-rt/lib/builtins/aarch64/sme-abi.S index 7c47336cfc579..d5510ac0cfa50 100644 --- a/compiler-rt/lib/builtins/aarch64/sme-abi.S +++ b/compiler-rt/lib/builtins/aarch64/sme-abi.S @@ -371,5 +371,5 @@ END_COMPILERRT_FUNCTION(__arm_sme_restore) NO_EXEC_STACK_DIRECTIVE -// GNU property note for BTI and PAC -GNU_PROPERTY_BTI_PAC +// GNU property note for BTI, PAC, and GCS +GNU_PROPERTY_BTI_PAC_GCS diff --git a/compiler-rt/lib/builtins/assembly.h b/compiler-rt/lib/builtins/assembly.h index 89372f18c84b2..d7db7d8189457 100644 --- a/compiler-rt/lib/builtins/assembly.h +++ b/compiler-rt/lib/builtins/assembly.h @@ -79,11 +79,12 @@ #define FUNC_ALIGN #endif -// BTI and PAC gnu property note +// BTI, PAC, and GCS gnu property note #define NT_GNU_PROPERTY_TYPE_0 5 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1 #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2 +#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4 #if defined(__ARM_FEATURE_BTI_DEFAULT) #define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI @@ -97,6 +98,12 @@ #define PAC_FLAG 0 #endif +#if defined(__ARM_FEATURE_GCS_DEFAULT) +#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS +#else +#define GCS_FLAG 0 +#endif + #define GNU_PROPERTY(type, value) \ .pushsection .note.gnu.property, "a" SEPARATOR \ .p2align 3 SEPARATOR \ @@ -118,11 +125,12 @@ #define BTI_J #endif -#if (BTI_FLAG | PAC_FLAG) != 0 -#define GNU_PROPERTY_BTI_PAC \ - GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG) +#if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0 +#define GNU_PROPERTY_BTI_PAC_GCS \ + GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \ + BTI_FLAG | PAC_FLAG | GCS_FLAG) #else -#define GNU_PROPERTY_BTI_PAC +#define GNU_PROPERTY_BTI_PAC_GCS #endif #if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM) diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64.c b/compiler-rt/lib/builtins/cpu_model/aarch64.c index be002dd71992a..d7880529ebe70 100644 --- a/compiler-rt/lib/builtins/cpu_model/aarch64.c +++ b/compiler-rt/lib/builtins/cpu_model/aarch64.c @@ -34,12 +34,12 @@ typedef struct __ifunc_arg_t { _Bool __aarch64_have_lse_atomics __attribute__((visibility("hidden"), nocommon)) = false; -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) // clang-format off: should not reorder sys/auxv.h alphabetically #include // clang-format on #include "aarch64/hwcap.inc" -#include "aarch64/lse_atomics/freebsd.inc" +#include "aarch64/lse_atomics/elf_aux_info.inc" #elif defined(__Fuchsia__) #include "aarch64/hwcap.inc" #include "aarch64/lse_atomics/fuchsia.inc" @@ -68,9 +68,9 @@ struct { // clang-format off #if defined(__APPLE__) #include "aarch64/fmv/apple.inc" -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__OpenBSD__) #include "aarch64/fmv/mrs.inc" -#include "aarch64/fmv/freebsd.inc" +#include "aarch64/fmv/elf_aux_info.inc" #elif defined(__Fuchsia__) #include "aarch64/fmv/fuchsia.inc" #elif defined(__ANDROID__) diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/freebsd.inc b/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/elf_aux_info.inc similarity index 100% rename from compiler-rt/lib/builtins/cpu_model/aarch64/fmv/freebsd.inc rename to compiler-rt/lib/builtins/cpu_model/aarch64/fmv/elf_aux_info.inc diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/freebsd.inc b/compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/elf_aux_info.inc similarity index 100% rename from compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/freebsd.inc rename to compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/elf_aux_info.inc diff --git a/compiler-rt/lib/builtins/crtbegin.c b/compiler-rt/lib/builtins/crtbegin.c index d5f7756308b09..447474bd0b692 100644 --- a/compiler-rt/lib/builtins/crtbegin.c +++ b/compiler-rt/lib/builtins/crtbegin.c @@ -54,22 +54,33 @@ static void __attribute__((used)) __do_init(void) { } #ifdef CRT_HAS_INITFINI_ARRAY -#if __has_feature(ptrauth_init_fini) +# if __has_feature(ptrauth_init_fini) // TODO: use __ptrauth-qualified pointers when they are supported on clang side -#if __has_feature(ptrauth_init_fini_address_discrimination) +# if __has_feature(ptrauth_init_fini_address_discrimination) __attribute__((section(".init_array"), used)) static void *__init = ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, ptrauth_blend_discriminator( &__init, __ptrauth_init_fini_discriminator)); -#else +# else __attribute__((section(".init_array"), used)) static void *__init = ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, __ptrauth_init_fini_discriminator); -#endif -#else +# endif +# elif __has_feature(ptrauth_calls) +# ifdef __aarch64__ +// If ptrauth_init_fini feature is not present, compiler emits raw unsigned +// pointers in .init_array. Use inline assembly to avoid implicit signing of +// __do_init function pointer with ptrauth_calls enabled. +__asm__(".pushsection .init_array,\"aw\",@init_array\n\t" + ".xword __do_init\n\t" + ".popsection"); +# else +# error "ptrauth_calls is only supported for AArch64" +# endif +# else __attribute__((section(".init_array"), used)) static void (*__init)(void) = __do_init; -#endif +# endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .init,\"ax\",@progbits\n\t" "call __do_init\n\t" @@ -125,22 +136,33 @@ static void __attribute__((used)) __do_fini(void) { } #ifdef CRT_HAS_INITFINI_ARRAY -#if __has_feature(ptrauth_init_fini) +# if __has_feature(ptrauth_init_fini) // TODO: use __ptrauth-qualified pointers when they are supported on clang side -#if __has_feature(ptrauth_init_fini_address_discrimination) +# if __has_feature(ptrauth_init_fini_address_discrimination) __attribute__((section(".fini_array"), used)) static void *__fini = ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, ptrauth_blend_discriminator( &__fini, __ptrauth_init_fini_discriminator)); -#else +# else __attribute__((section(".fini_array"), used)) static void *__fini = ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, __ptrauth_init_fini_discriminator); -#endif -#else +# endif +# elif __has_feature(ptrauth_calls) +# ifdef __aarch64__ +// If ptrauth_init_fini feature is not present, compiler emits raw unsigned +// pointers in .fini_array. Use inline assembly to avoid implicit signing of +// __do_fini function pointer with ptrauth_calls enabled. +__asm__(".pushsection .fini_array,\"aw\",@fini_array\n\t" + ".xword __do_fini\n\t" + ".popsection"); +# else +# error "ptrauth_calls is only supported for AArch64" +# endif +# else __attribute__((section(".fini_array"), used)) static void (*__fini)(void) = __do_fini; -#endif +# endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .fini,\"ax\",@progbits\n\t" "call __do_fini\n\t" diff --git a/compiler-rt/lib/gwp_asan/tests/basic.cpp b/compiler-rt/lib/gwp_asan/tests/basic.cpp index 88e7ed14a5c2f..7d36a2ee1f947 100644 --- a/compiler-rt/lib/gwp_asan/tests/basic.cpp +++ b/compiler-rt/lib/gwp_asan/tests/basic.cpp @@ -65,11 +65,12 @@ TEST_F(DefaultGuardedPoolAllocator, NonPowerOfTwoAlignment) { // Added multi-page slots? You'll need to expand this test. TEST_F(DefaultGuardedPoolAllocator, TooBigForSinglePageSlots) { - EXPECT_EQ(nullptr, GPA.allocate(0x1001, 0)); - EXPECT_EQ(nullptr, GPA.allocate(0x1001, 1)); - EXPECT_EQ(nullptr, GPA.allocate(0x1001, 0x1000)); - EXPECT_EQ(nullptr, GPA.allocate(1, 0x2000)); - EXPECT_EQ(nullptr, GPA.allocate(0, 0x2000)); + size_t PageSize = sysconf(_SC_PAGESIZE); + EXPECT_EQ(nullptr, GPA.allocate(PageSize + 1, 0)); + EXPECT_EQ(nullptr, GPA.allocate(PageSize + 1, 1)); + EXPECT_EQ(nullptr, GPA.allocate(PageSize + 1, PageSize)); + EXPECT_EQ(nullptr, GPA.allocate(1, 2 * PageSize)); + EXPECT_EQ(nullptr, GPA.allocate(0, 2 * PageSize)); } TEST_F(CustomGuardedPoolAllocator, AllocAllSlots) { diff --git a/compiler-rt/lib/gwp_asan/tests/never_allocated.cpp b/compiler-rt/lib/gwp_asan/tests/never_allocated.cpp index 2f695b4379861..37a4b384e4ac0 100644 --- a/compiler-rt/lib/gwp_asan/tests/never_allocated.cpp +++ b/compiler-rt/lib/gwp_asan/tests/never_allocated.cpp @@ -13,8 +13,10 @@ #include "gwp_asan/tests/harness.h" TEST_P(BacktraceGuardedPoolAllocatorDeathTest, NeverAllocated) { + size_t PageSize = sysconf(_SC_PAGESIZE); + SCOPED_TRACE(""); - void *Ptr = GPA.allocate(0x1000); + void *Ptr = GPA.allocate(PageSize); GPA.deallocate(Ptr); std::string DeathNeedle = @@ -23,7 +25,7 @@ TEST_P(BacktraceGuardedPoolAllocatorDeathTest, NeverAllocated) { // Trigger a guard page in a completely different slot that's never allocated. // Previously, there was a bug that this would result in nullptr-dereference // in the posix crash handler. - char *volatile NeverAllocatedPtr = static_cast(Ptr) + 0x3000; + char *volatile NeverAllocatedPtr = static_cast(Ptr) + 3 * PageSize; if (!Recoverable) { EXPECT_DEATH(*NeverAllocatedPtr = 0, DeathNeedle); return; @@ -37,8 +39,8 @@ TEST_P(BacktraceGuardedPoolAllocatorDeathTest, NeverAllocated) { GetOutputBuffer().clear(); for (size_t i = 0; i < 100; ++i) { *NeverAllocatedPtr = 0; - *(NeverAllocatedPtr + 0x2000) = 0; - *(NeverAllocatedPtr + 0x3000) = 0; + *(NeverAllocatedPtr + 2 * PageSize) = 0; + *(NeverAllocatedPtr + 3 * PageSize) = 0; ASSERT_TRUE(GetOutputBuffer().empty()); } diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S b/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S index fd20825e3dacc..825f411565098 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S +++ b/compiler-rt/lib/hwasan/hwasan_interceptors_vfork.S @@ -11,4 +11,4 @@ NO_EXEC_STACK_DIRECTIVE -GNU_PROPERTY_BTI_PAC +GNU_PROPERTY_BTI_PAC_GCS diff --git a/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S b/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S index 0c0abb6de861f..b8d98b09ada25 100644 --- a/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S +++ b/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S @@ -99,4 +99,4 @@ ASM_TRAMPOLINE_ALIAS(_setjmp, setjmp) // We do not need executable stack. NO_EXEC_STACK_DIRECTIVE -GNU_PROPERTY_BTI_PAC +GNU_PROPERTY_BTI_PAC_GCS diff --git a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S index fd060c51cd8e2..be82475101c8c 100644 --- a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S +++ b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S @@ -157,4 +157,4 @@ mismatch: // We do not need executable stack. NO_EXEC_STACK_DIRECTIVE -GNU_PROPERTY_BTI_PAC +GNU_PROPERTY_BTI_PAC_GCS diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index 08c2be47f5358..673f284b6a043 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc @@ -344,12 +344,16 @@ static void ioctl_table_fill() { _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int)); _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int)); _(TCFLSH, NONE, 0); +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS _(TCGETS, WRITE, struct_termios_sz); +# endif _(TCSBRK, NONE, 0); _(TCSBRKP, NONE, 0); +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS _(TCSETS, READ, struct_termios_sz); _(TCSETSF, READ, struct_termios_sz); _(TCSETSW, READ, struct_termios_sz); +# endif _(TCXONC, NONE, 0); _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz); _(TIOCGSOFTCAR, WRITE, sizeof(int)); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S index cdfa6f1d7f53b..5066953980af7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S @@ -43,6 +43,6 @@ ASM_SIZE(vfork) ASM_INTERCEPTOR_TRAMPOLINE(vfork) ASM_TRAMPOLINE_ALIAS(vfork, vfork) -GNU_PROPERTY_BTI_PAC +GNU_PROPERTY_BTI_PAC_GCS #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 16caf699a4c24..ea5f2e8f8e022 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -1287,7 +1287,7 @@ uptr GetPageSize() { uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) { # if SANITIZER_HAIKU - int cookie = 0; + int32_t cookie = 0; image_info info; const char *argv0 = ""; while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { @@ -1987,7 +1987,10 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const { # elif SANITIZER_NETBSD uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR]; # elif SANITIZER_HAIKU - uptr err = ucontext->uc_mcontext.r13; + uptr err = 0; // FIXME: ucontext->uc_mcontext.r13; + // The err register was added on the main branch and not + // available with the current release. To be reverted later. + // https://github.com/haiku/haiku/commit/11adda21aa4e6b24f71a496868a44d7607bc3764 # elif SANITIZER_SOLARIS && defined(__i386__) const int Err = 13; uptr err = ucontext->uc_mcontext.gregs[Err]; @@ -2617,6 +2620,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.mc_eip; *bp = ucontext->uc_mcontext.mc_ebp; *sp = ucontext->uc_mcontext.mc_esp; +# elif SANITIZER_HAIKU + ucontext_t *ucontext = (ucontext_t *)context; + *pc = ucontext->uc_mcontext.eip; + *bp = ucontext->uc_mcontext.ebp; + *sp = ucontext->uc_mcontext.esp; # else ucontext_t *ucontext = (ucontext_t *)context; # if SANITIZER_SOLARIS diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index f5cb85bc1bf30..530ff90c4cd16 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -29,6 +29,7 @@ # include "sanitizer_solaris.h" # if SANITIZER_HAIKU +# define _GNU_SOURCE # define _DEFAULT_SOURCE # endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 196c0a988478e..13099fe84b0aa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -482,4 +482,19 @@ # define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0 #endif +#if SANITIZER_LINUX +# if SANITIZER_GLIBC +// Workaround for +// glibc/commit/3d3572f59059e2b19b8541ea648a6172136ec42e +// Linux: Keep termios ioctl constants strictly internal +# if __GLIBC_PREREQ(2, 41) +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 0 +# else +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1 +# endif +# else +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1 +# endif +#endif + #endif // SANITIZER_PLATFORM_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp index 4c1e005289230..c4fa1e3c1f6fa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp @@ -71,14 +71,8 @@ #include #include #include -#include -#include -#include -#include -#include #include #include -#include #include #include #include @@ -370,22 +364,6 @@ const int si_SEGV_MAPERR = SEGV_MAPERR; const int si_SEGV_ACCERR = SEGV_ACCERR; const int unvis_valid = UNVIS_VALID; const int unvis_validpush = UNVIS_VALIDPUSH; - -const unsigned MD5_CTX_sz = sizeof(MD5_CTX); -const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH; - -#define SHA2_CONST(LEN) \ - const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \ - const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \ - const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \ - const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH - -SHA2_CONST(224); -SHA2_CONST(256); -SHA2_CONST(384); -SHA2_CONST(512); - -#undef SHA2_CONST } // namespace __sanitizer using namespace __sanitizer; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h index 382b67ce78ebd..1cbb40e0b2ffc 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h @@ -710,22 +710,6 @@ extern unsigned IOCTL_KDSKBMODE; extern const int si_SEGV_MAPERR; extern const int si_SEGV_ACCERR; -extern const unsigned MD5_CTX_sz; -extern const unsigned MD5_return_length; - -#define SHA2_EXTERN(LEN) \ - extern const unsigned SHA##LEN##_CTX_sz; \ - extern const unsigned SHA##LEN##_return_length; \ - extern const unsigned SHA##LEN##_block_length; \ - extern const unsigned SHA##LEN##_digest_length - -SHA2_EXTERN(224); -SHA2_EXTERN(256); -SHA2_EXTERN(384); -SHA2_EXTERN(512); - -#undef SHA2_EXTERN - struct __sanitizer_cap_rights { u64 cr_rights[2]; }; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp index aacd28c55ceaa..435f3b2861dc9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp @@ -498,7 +498,6 @@ struct urio_command { #include #include #include -#include #include #include #include @@ -515,7 +514,7 @@ struct urio_command { #include #if defined(__x86_64__) -#include +#include #endif // clang-format on diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index 7a89bf1c74985..ea8cc306268cb 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -779,16 +779,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER; #endif // SOUND_VERSION unsigned IOCTL_TCFLSH = TCFLSH; - unsigned IOCTL_TCGETA = TCGETA; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS unsigned IOCTL_TCGETS = TCGETS; +# endif unsigned IOCTL_TCSBRK = TCSBRK; unsigned IOCTL_TCSBRKP = TCSBRKP; - unsigned IOCTL_TCSETA = TCSETA; - unsigned IOCTL_TCSETAF = TCSETAF; - unsigned IOCTL_TCSETAW = TCSETAW; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS unsigned IOCTL_TCSETS = TCSETS; unsigned IOCTL_TCSETSF = TCSETSF; unsigned IOCTL_TCSETSW = TCSETSW; +# endif unsigned IOCTL_TCXONC = TCXONC; unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS; unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index a2b6c37d5450c..41d60c8d59fbe 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -102,6 +102,8 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) # if defined(_ABIN32) && _MIPS_SIM == _ABIN32 : FIRST_32_SECOND_64(176, 216); +# elif SANITIZER_MUSL + : FIRST_32_SECOND_64(160, 208); # else : FIRST_32_SECOND_64(160, 216); # endif @@ -476,6 +478,30 @@ struct __sanitizer_cmsghdr { int cmsg_level; int cmsg_type; }; +# elif SANITIZER_MUSL +struct __sanitizer_msghdr { + void *msg_name; + unsigned msg_namelen; + struct __sanitizer_iovec *msg_iov; + int msg_iovlen; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + void *msg_control; + unsigned msg_controllen; +# if SANITIZER_WORDSIZE == 64 + int __pad2; +# endif + int msg_flags; +}; +struct __sanitizer_cmsghdr { + unsigned cmsg_len; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + int cmsg_level; + int cmsg_type; +}; # else // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but // many implementations don't conform to the standard. @@ -603,7 +629,7 @@ typedef unsigned long __sanitizer_sigset_t; # elif SANITIZER_APPLE typedef unsigned __sanitizer_sigset_t; # elif SANITIZER_HAIKU -typedef unsigned long __sanitizer_sigset_t; +typedef unsigned long long __sanitizer_sigset_t; # elif SANITIZER_LINUX struct __sanitizer_sigset_t { // The size is determined by looking at sizeof of real sigset_t on linux. @@ -1312,16 +1338,14 @@ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG; extern unsigned IOCTL_SNDCTL_COPR_WCODE; extern unsigned IOCTL_SNDCTL_COPR_WDATA; extern unsigned IOCTL_TCFLSH; -extern unsigned IOCTL_TCGETA; -extern unsigned IOCTL_TCGETS; extern unsigned IOCTL_TCSBRK; extern unsigned IOCTL_TCSBRKP; -extern unsigned IOCTL_TCSETA; -extern unsigned IOCTL_TCSETAF; -extern unsigned IOCTL_TCSETAW; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS +extern unsigned IOCTL_TCGETS; extern unsigned IOCTL_TCSETS; extern unsigned IOCTL_TCSETSF; extern unsigned IOCTL_TCSETSW; +# endif extern unsigned IOCTL_TCXONC; extern unsigned IOCTL_TIOCGLCKTRMIOS; extern unsigned IOCTL_TIOCGSOFTCAR; diff --git a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp index 05065444a70c5..612317b3c3293 100644 --- a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp @@ -183,7 +183,8 @@ TEST_F(ScudoWrappersCDeathTest, Malloc) { // process doing free(P) is not a double free. EXPECT_DEATH( { - void *Ptr = malloc(Size); + // Note: volatile here prevents the calls from being optimized out. + void *volatile Ptr = malloc(Size); free(Ptr); free(Ptr); }, diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S index 7d920bee4a2db..f1d11a3e7f54f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S @@ -222,6 +222,6 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) NO_EXEC_STACK_DIRECTIVE -GNU_PROPERTY_BTI_PAC +GNU_PROPERTY_BTI_PAC_GCS #endif diff --git a/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cpp b/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cpp index 3e28ffde46ab6..dc3ead9e8436c 100644 --- a/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/release_to_os_test.cpp @@ -6,6 +6,7 @@ // RUN: %env_asan_opts=allocator_release_to_os_interval_ms=-1 %run %t force 2>&1 | FileCheck %s --check-prefix=FORCE_RELEASE // REQUIRES: x86_64-target-arch +// REQUIRES: page-size-4096 #include #include diff --git a/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py b/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py index dceb7cde7218b..5f5486af3779f 100644 --- a/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py +++ b/compiler-rt/test/cfi/cross-dso/lit.local.cfg.py @@ -12,3 +12,7 @@ def getRoot(config): # Android O (API level 26) has support for cross-dso cfi in libdl.so. if config.android and "android-26" not in config.available_features: config.unsupported = True + +# The runtime library only supports 4K pages. +if "page-size-4096" not in config.available_features: + config.unsupported = True diff --git a/compiler-rt/test/dfsan/atomic.cpp b/compiler-rt/test/dfsan/atomic.cpp index 22ee323c752f8..73e1cbd17a7cd 100644 --- a/compiler-rt/test/dfsan/atomic.cpp +++ b/compiler-rt/test/dfsan/atomic.cpp @@ -1,9 +1,12 @@ -// RUN: %clangxx_dfsan %s -fno-exceptions -o %t && %run %t -// RUN: %clangxx_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 %s -fno-exceptions -o %t && %run %t +// RUN: %clangxx_dfsan %s -fno-exceptions -D_GLIBCXX_NO_ASSERTIONS -o %t && %run %t +// RUN: %clangxx_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 %s -fno-exceptions -D_GLIBCXX_NO_ASSERTIONS -o %t && %run %t // // Use -fno-exceptions to turn off exceptions to avoid instrumenting // __cxa_begin_catch, std::terminate and __gxx_personality_v0. // +// Use -D_GLIBCXX_NO_ASSERTIONS to avoid depending on +// std::__glibcxx_assert_fail with gcc >= 15. +// // TODO: Support builtin atomics. For example, https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html // DFSan instrumentation pass cannot identify builtin callsites yet. diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 877718c703ba7..13ae9e7753001 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -503,7 +503,7 @@ def get_ios_commands_dir(): # Define %arch to check for architecture-dependent output. config.substitutions.append(("%arch", (config.host_arch))) -if config.host_os == "Windows": +if os.name == "nt": # FIXME: This isn't quite right. Specifically, it will succeed if the program # does not crash but exits with a non-zero exit code. We ought to merge # KillTheDoctor and not --crash to make the latter more useful and remove the @@ -965,6 +965,23 @@ def is_windows_lto_supported(): else: config.available_features.add("memprof-shadow-scale-3") + +def target_page_size(): + try: + proc = subprocess.Popen( + f"{emulator or ''} python3", + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + out, err = proc.communicate(b'import os; print(os.sysconf("SC_PAGESIZE"))') + return int(out) + except: + return 4096 + + +config.available_features.add(f"page-size-{target_page_size()}") + if config.expensive_checks: config.available_features.add("expensive_checks") diff --git a/compiler-rt/test/msan/dtls_test.c b/compiler-rt/test/msan/dtls_test.c index 3c384256147a0..6daaab0ae0b8d 100644 --- a/compiler-rt/test/msan/dtls_test.c +++ b/compiler-rt/test/msan/dtls_test.c @@ -11,6 +11,7 @@ // Reports use-of-uninitialized-value, not analyzed XFAIL: target={{.*netbsd.*}} + UNSUPPORTED: aarch64-target-arch */ diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp index 9d7d46b462a88..cc76804aed210 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/odd_stack_size.cpp @@ -1,4 +1,5 @@ // RUN: %clangxx -O1 %s -o %t && %run %t +// REQUIRES: page-size-4096 // UNSUPPORTED: android // Fail on powerpc64 bots with: diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp index 0fa77200bf1cc..c7a5534696361 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp @@ -11,6 +11,9 @@ // FIXME: This mode uses 32bit allocator without purge. // UNSUPPORTED: hwasan-aliasing +// Page size is hardcoded below, but test still fails even if not hardcoded. +// REQUIRES: page-size-4096 + #include #include #include diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp index c288e1d69baf9..3e9ff924a3c4a 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/resize_tls_dynamic.cpp @@ -11,6 +11,9 @@ // FIXME: Investigate // UNSUPPORTED: target=powerpc64{{.*}} +// Fails because AArch64 uses TLSDESC instead of __tls_get_addr. +// UNSUPPORTED: aarch64-target-arch + #include #ifndef BUILD_DSO diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_get_addr.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_get_addr.c index 0aff6039ac4e8..a4a4f64ed3706 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_get_addr.c +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/tls_get_addr.c @@ -13,6 +13,9 @@ // FIXME: Fails for unknown reasons. // UNSUPPORTED: powerpc64le-target-arch +// Fails because AArch64 uses TLSDESC instead of __tls_get_addr. +// UNSUPPORTED: aarch64-target-arch + #ifndef BUILD_SO # include # include diff --git a/cross-project-tests/CMakeLists.txt b/cross-project-tests/CMakeLists.txt index b4b1f47626073..192db87043177 100644 --- a/cross-project-tests/CMakeLists.txt +++ b/cross-project-tests/CMakeLists.txt @@ -19,11 +19,12 @@ set(CROSS_PROJECT_TEST_DEPS FileCheck check-gdb-llvm-support count - llvm-dwarfdump + llvm-ar llvm-config + llvm-dwarfdump llvm-objdump - split-file not + split-file ) if ("clang" IN_LIST LLVM_ENABLE_PROJECTS) diff --git a/cross-project-tests/dtlto/ld-archive-thin.test b/cross-project-tests/dtlto/ld-archive-thin.test new file mode 100644 index 0000000000000..979da5423962e --- /dev/null +++ b/cross-project-tests/dtlto/ld-archive-thin.test @@ -0,0 +1,97 @@ +REQUIRES: ld.lld,llvm-ar + +## Test that a DTLTO link succeeds and outputs the expected set of files +## correctly when thin archives are present. + +RUN: rm -rf %t && split-file %s %t && cd %t + +## Compile bitcode. -O2 is required for cross-module importing. +RUN: %clang -O2 --target=x86_64-linux-gnu -flto=thin -c \ +RUN: foo.c bar.c dog.c cat.c start.c + +## Generate thin archives. +RUN: llvm-ar rcs foo.a foo.o --thin +## Create this bitcode thin archive in a subdirectory to test the expansion of +## the path to a bitcode file that is referenced using "..", e.g., in this case +## "../bar.o". +RUN: mkdir lib +RUN: llvm-ar rcs lib/bar.a bar.o --thin +## Create this bitcode thin archive with an absolute path entry containing "..". +RUN: llvm-ar rcs dog.a %t/lib/../dog.o --thin +## The bitcode member of cat.a will not be used in the link. +RUN: llvm-ar rcs cat.a cat.o --thin +RUN: llvm-ar rcs start.a start.o --thin + +## Link from a different directory to ensure that thin archive member paths are +## resolved correctly relative to the archive locations. +RUN: mkdir %t/out && cd %t/out + +RUN: %clang --target=x86_64-linux-gnu -flto=thin -fuse-ld=lld %t/foo.a %t/lib/bar.a ../start.a %t/cat.a \ +RUN: -Wl,--whole-archive ../dog.a \ +RUN: -fthinlto-distributor=%python \ +RUN: -Xthinlto-distributor=%llvm_src_root/utils/dtlto/local.py \ +RUN: -Wl,--save-temps -nostdlib -Werror + +## Check that the required output files have been created. +RUN: ls | sort | FileCheck %s + +## No files are expected before. +CHECK-NOT: {{.}} + +## JSON jobs description. +CHECK: {{^}}a.[[PID:[a-zA-Z0-9_]+]].dist-file.json{{$}} + +## Native output object files and individual summary index files. +CHECK: {{^}}bar.3.[[PID]].native.o{{$}} +CHECK: {{^}}bar.3.[[PID]].native.o.thinlto.bc{{$}} +CHECK: {{^}}dog.1.[[PID]].native.o{{$}} +CHECK: {{^}}dog.1.[[PID]].native.o.thinlto.bc{{$}} +CHECK: {{^}}foo.2.[[PID]].native.o{{$}} +CHECK: {{^}}foo.2.[[PID]].native.o.thinlto.bc{{$}} +CHECK: {{^}}start.4.[[PID]].native.o{{$}} +CHECK: {{^}}start.4.[[PID]].native.o.thinlto.bc{{$}} + +## No files are expected after. +CHECK-NOT: {{.}} + + +## It is important that cross-module inlining occurs for this test to show that Clang can +## successfully load the bitcode file dependencies recorded in the summary indices. +## Explicitly check that the expected importing has occurred. + +RUN: llvm-dis start.4.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis dog.1.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,DOG,START + +RUN: llvm-dis foo.2.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis bar.3.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +FOO-DAG: foo.o +BAR-DAG: bar.o +DOG-DAG: dog.o +START-DAG: start.o + + +#--- foo.c +extern int bar(int), _start(int); +__attribute__((retain)) int foo(int x) { return x + bar(x) + _start(x); } + +#--- bar.c +extern int foo(int), _start(int); +__attribute__((retain)) int bar(int x) { return x + foo(x) + _start(x); } + +#--- dog.c +extern int foo(int), bar(int), _start(int); +__attribute__((retain)) int dog(int x) { return x + foo(x) + bar(x) + _start(x); } + +#--- cat.c +__attribute__((retain)) void cat(int x) {} + +#--- start.c +extern int foo(int), bar(int); +__attribute__((retain)) int _start(int x) { return x + foo(x) + bar(x); } diff --git a/cross-project-tests/dtlto/ld-dtlto.c b/cross-project-tests/dtlto/ld-dtlto.c index 3ee962346bd4a..7dffe2e015bcb 100644 --- a/cross-project-tests/dtlto/ld-dtlto.c +++ b/cross-project-tests/dtlto/ld-dtlto.c @@ -5,13 +5,11 @@ // RUN: rm -rf %t && mkdir %t && cd %t -// RUN: %clang --target=x86_64-linux-gnu -c -flto=thin %s -o dtlto.o - -// RUN: ld.lld dtlto.o \ -// RUN: --thinlto-distributor=%python \ -// RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/local.py \ -// RUN: --thinlto-remote-compiler=%clang \ -// RUN: --thinlto-remote-compiler-arg=--save-temps +// RUN: %clang --target=x86_64-linux-gnu %s -flto=thin -fuse-ld=lld \ +// RUN: -fthinlto-distributor=%python \ +// RUN: -Xthinlto-distributor=%llvm_src_root/utils/dtlto/local.py \ +// RUN: -Wl,--thinlto-remote-compiler-arg=--save-temps \ +// RUN: -nostdlib -Werror /// Check that the required output files have been created. // RUN: ls | sort | FileCheck %s @@ -22,18 +20,15 @@ /// Linked ELF. // CHECK: {{^}}a.out{{$}} -/// Produced by the bitcode compilation. -// CHECK-NEXT: {{^}}dtlto.o{{$}} - /// --save-temps output for the backend compilation. -// CHECK-NEXT: {{^}}dtlto.s{{$}} -// CHECK-NEXT: {{^}}dtlto.s.0.preopt.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.1.promote.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.2.internalize.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.3.import.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.4.opt.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.5.precodegen.bc{{$}} -// CHECK-NEXT: {{^}}dtlto.s.resolution.txt{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP:[a-zA-Z0-9_]+]].s{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.0.preopt.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.1.promote.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.2.internalize.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.3.import.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.4.opt.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.5.precodegen.bc{{$}} +// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.resolution.txt{{$}} /// No files are expected after. // CHECK-NOT: {{.}} diff --git a/cross-project-tests/dtlto/link-archive-thin.test b/cross-project-tests/dtlto/link-archive-thin.test new file mode 100644 index 0000000000000..fbd8fd67300cf --- /dev/null +++ b/cross-project-tests/dtlto/link-archive-thin.test @@ -0,0 +1,93 @@ +REQUIRES: lld-link + +## Test that a DTLTO link succeeds and outputs the expected set of files +## correctly when thin archives are present. + +RUN: rm -rf %t && split-file %s %t && cd %t + +## Compile bitcode. -O2 is required for cross-module importing. +RUN: %clang -O2 --target=x86_64-pc-windows-msvc -flto=thin -c \ +RUN: foo.c bar.c dog.c cat.c start.c + +## Generate thin archives. +RUN: lld-link /lib /llvmlibthin /out:foo.lib foo.o +## Create this bitcode thin archive in a subdirectory to test the expansion of +## the path to a bitcode file that is referenced using "..", e.g., in this case +## "../bar.o". +RUN: mkdir lib +RUN: lld-link /lib /llvmlibthin /out:lib/bar.lib bar.o +## Create this bitcode thin archive with an absolute path entry containing "..". +RUN: lld-link /lib /llvmlibthin /out:dog.lib %t/lib/../dog.o +RUN: lld-link /lib /llvmlibthin /out:cat.lib cat.o +RUN: lld-link /lib /llvmlibthin /out:start.lib start.o + +## Link from a different directory to ensure that thin archive member paths are +## resolved correctly relative to the archive locations. +RUN: mkdir %t/out && cd %t/out +RUN: lld-link /subsystem:console /machine:x64 /entry:start /out:my.exe \ +RUN: %t/foo.lib %t/lib/bar.lib ../start.lib %t/cat.lib \ +RUN: /includeoptional:dog ../dog.lib \ +RUN: -thinlto-distributor:%python \ +RUN: -thinlto-distributor-arg:%llvm_src_root/utils/dtlto/local.py \ +RUN: -thinlto-remote-compiler:%clang \ +RUN: /lldsavetemps + +## Check that the required output files have been created. +RUN: ls | FileCheck %s --check-prefix=OUTPUTS --implicit-check-not=cat + +## JSON jobs description. +OUTPUTS-DAG: my.[[PID:[a-zA-Z0-9_]+]].dist-file.json + +## Individual summary index files. +OUTPUTS-DAG: start.1.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: dog.2.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: foo.3.[[PID]].native.o.thinlto.bc{{$}} +OUTPUTS-DAG: bar.4.[[PID]].native.o.thinlto.bc{{$}} + +## Native output object files. +OUTPUTS-DAG: start.1.[[PID]].native.o{{$}} +OUTPUTS-DAG: dog.2.[[PID]].native.o{{$}} +OUTPUTS-DAG: foo.3.[[PID]].native.o{{$}} +OUTPUTS-DAG: bar.4.[[PID]].native.o{{$}} + + +## It is important that cross-module inlining occurs for this test to show that Clang can +## successfully load the bitcode file dependencies recorded in the summary indices. +## Explicitly check that the expected importing has occurred. + +RUN: llvm-dis start.1.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis dog.2.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,DOG,START + +RUN: llvm-dis foo.3.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +RUN: llvm-dis bar.4.*.native.o.thinlto.bc -o - | \ +RUN: FileCheck %s --check-prefixes=FOO,BAR,START + +FOO-DAG: foo.o +BAR-DAG: bar.o +DOG-DAG: dog.o +START-DAG: start.o + + +#--- foo.c +extern int bar(int), start(int); +__attribute__((retain)) int foo(int x) { return x + bar(x) + start(x); } + +#--- bar.c +extern int foo(int), start(int); +__attribute__((retain)) int bar(int x) { return x + foo(x) + start(x); } + +#--- dog.c +extern int foo(int), bar(int), start(int); +__attribute__((retain)) int dog(int x) { return x + foo(x) + bar(x) + start(x); } + +#--- cat.c +__attribute__((retain)) void cat(int x) {} + +#--- start.c +extern int foo(int), bar(int); +__attribute__((retain)) int start(int x) { return x + foo(x) + bar(x); } diff --git a/cross-project-tests/dtlto/link-dtlto.c b/cross-project-tests/dtlto/link-dtlto.c new file mode 100644 index 0000000000000..0ab4ec57f115d --- /dev/null +++ b/cross-project-tests/dtlto/link-dtlto.c @@ -0,0 +1,41 @@ +// REQUIRES: lld-link + +/// Simple test that DTLTO works with a single input bitcode file and that +/// --save-temps can be applied to the remote compilation. + +// RUN: rm -rf %t && mkdir %t && cd %t + +// RUN: %clang --target=x86_64-pc-windows-msvc -c -flto=thin %s -o dtlto.obj + +// RUN: lld-link /subsystem:console /entry:_start dtlto.obj \ +// RUN: -thinlto-distributor:%python \ +// RUN: -thinlto-distributor-arg:%llvm_src_root/utils/dtlto/local.py \ +// RUN: -thinlto-remote-compiler:%clang \ +// RUN: -thinlto-remote-compiler-arg:--save-temps + +/// Check that the required output files have been created. +// RUN: ls | sort | FileCheck %s + +/// No files are expected before. +// CHECK-NOT: {{.}} + +/// Linked ELF. +// CHECK: {{^}}dtlto.exe{{$}} + +/// Produced by the bitcode compilation. +// CHECK-NEXT: {{^}}dtlto.obj{{$}} + +/// --save-temps output for the backend compilation. +// CHECK-NEXT: {{^}}dtlto.s{{$}} +// CHECK-NEXT: {{^}}dtlto.s.0.preopt.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.1.promote.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.2.internalize.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.3.import.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.4.opt.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.5.precodegen.bc{{$}} +// CHECK-NEXT: {{^}}dtlto.s.resolution.txt{{$}} + +/// No files are expected after. +// CHECK-NOT: {{.}} + +int _start() { return 0; } diff --git a/cross-project-tests/lit.cfg.py b/cross-project-tests/lit.cfg.py index b35c643ac898c..ac27753472646 100644 --- a/cross-project-tests/lit.cfg.py +++ b/cross-project-tests/lit.cfg.py @@ -19,7 +19,7 @@ config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) # suffixes: A list of file extensions to treat as test files. -config.suffixes = [".c", ".cl", ".cpp", ".m"] +config.suffixes = [".c", ".cl", ".cpp", ".m", ".test"] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent @@ -107,6 +107,8 @@ def get_required_attr(config, attr_name): if lldb_path is not None: config.available_features.add("lldb") +if llvm_config.use_llvm_tool("llvm-ar"): + config.available_features.add("llvm-ar") def configure_dexter_substitutions(): """Configure substitutions for host platform and return list of dependencies""" diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake index e51590fdae3d3..58541609829c4 100644 --- a/flang-rt/cmake/modules/AddFlangRT.cmake +++ b/flang-rt/cmake/modules/AddFlangRT.cmake @@ -286,27 +286,6 @@ function (add_flangrt_library name) target_compile_options(${tgtname} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS) endif () - # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI - # should only depend on msvcrt/ucrt. LLVM still emits libgcc/compiler-rt - # functions in some cases like 128-bit integer math (__udivti3, __modti3, - # __fixsfti, __floattidf, ...) that msvc does not support. We are injecting a - # dependency to Compiler-RT's builtin library where these are implemented. - if (MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") - if (FLANG_RT_BUILTINS_LIBRARY) - target_compile_options(${tgtname} PRIVATE "$<$:-Xclang>" "$<$:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") - endif () - endif () - if (MSVC AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang") - if (FLANG_RT_BUILTINS_LIBRARY) - target_compile_options(${tgtname} PRIVATE "$<$:-Xflang>" "$<$:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") - else () - message(WARNING "Did not find libclang_rt.builtins.lib. - LLVM may emit builtins that are not implemented in msvcrt/ucrt and - instead falls back to builtins from Compiler-RT. Linking with ${tgtname} - may result in a linker error.") - endif () - endif () - # Non-GTest unittests depend on LLVMSupport if (ARG_LINK_TO_LLVM) if (LLVM_LINK_LLVM_DYLIB) diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt index 332c0872e065f..dc2db1d9902cb 100644 --- a/flang-rt/lib/runtime/CMakeLists.txt +++ b/flang-rt/lib/runtime/CMakeLists.txt @@ -251,19 +251,33 @@ else() add_win_flangrt_runtime(STATIC dynamic MultiThreadedDLL INSTALL_WITH_TOOLCHAIN) add_win_flangrt_runtime(STATIC dynamic_dbg MultiThreadedDebugDLL INSTALL_WITH_TOOLCHAIN) - # Unittests link against LLVMSupport which is using CMake's default runtime - # library selection, which is either MultiThreadedDLL or MultiThreadedDebugDLL - # depending on the configuration. They have to match or linking will fail. + # Unittests link against LLVMSupport. If CMAKE_MSVC_RUNTIME_LIBRARY is set, + # that will have been used for LLVMSupport so it must also be used here. + # Otherwise this will use CMake's default runtime library selection, which + # is either MultiThreadedDLL or MultiThreadedDebugDLL depending on the configuration. + # They have to match or linking will fail. if (GENERATOR_IS_MULTI_CONFIG) # We cannot select an ALIAS library because it may be different # per configuration. Fallback to CMake's default. add_win_flangrt_runtime(STATIC unittest "" EXCLUDE_FROM_ALL) else () - string(TOLOWER ${CMAKE_BUILD_TYPE} build_type) - if (build_type STREQUAL "debug") - add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic_dbg) - else () - add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic) - endif () + # Check if CMAKE_MSVC_RUNTIME_LIBRARY was set. + if (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreaded") + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.static) + elseif (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDLL") + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic) + elseif (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDebug") + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.static_dbg) + elseif (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDebugDLL") + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic_dbg) + else() + # Default based on the build type. + string(TOLOWER ${CMAKE_BUILD_TYPE} build_type) + if (build_type STREQUAL "debug") + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic_dbg) + else () + add_library(flang_rt.runtime.unittest ALIAS flang_rt.runtime.dynamic) + endif () + endif() endif () endif() diff --git a/flang-rt/unittests/CMakeLists.txt b/flang-rt/unittests/CMakeLists.txt index 5282196174134..fd63ad11dcf43 100644 --- a/flang-rt/unittests/CMakeLists.txt +++ b/flang-rt/unittests/CMakeLists.txt @@ -60,6 +60,27 @@ function(add_flangrt_unittest_offload_properties target) endif() endfunction() +# flang-rt on Windows requires compiler-rt for some symbols. For binaries built +# with flang this dependency is added by the flang driver, but since the unit +# tests are built with clang we need to add the dependency manually. +function(add_flangrt_dependent_libs target) + if (MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (FLANG_RT_BUILTINS_LIBRARY) + target_compile_options(${target} PRIVATE "$<$:-Xclang>" "$<$:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") + endif () + endif () + if (MSVC AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang") + if (FLANG_RT_BUILTINS_LIBRARY) + target_compile_options(${target} PRIVATE "$<$:-Xflang>" "$<$:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") + else () + message(WARNING "Did not find libclang_rt.builtins.lib. + LLVM may emit builtins that are not implemented in msvcrt/ucrt and + instead falls back to builtins from Compiler-RT. Linking with ${tgtname} + may result in a linker error.") + endif () + endif () +endfunction() + function(add_flangrt_unittest test_dirname) cmake_parse_arguments(ARG @@ -72,14 +93,7 @@ function(add_flangrt_unittest test_dirname) target_link_libraries(${test_dirname} PRIVATE ${ARG_LINK_LIBS}) add_flangrt_unittest_offload_properties(${test_dirname}) - - # Required because LLVMSupport is compiled with this option. - # FIXME: According to CMake documentation, this is the default. Why is it - # needed? LLVM's add_unittest doesn't set it either. - set_target_properties(${test_dirname} - PROPERTIES - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL" - ) + add_flangrt_dependent_libs(${test_dirname}) endfunction() function(add_flangrt_nongtest_unittest test_name) @@ -99,6 +113,7 @@ function(add_flangrt_nongtest_unittest test_name) set_target_properties(${test_name}${suffix} PROPERTIES FOLDER "Flang-RT/Tests/Unit") target_link_libraries(${test_name}${suffix} PRIVATE NonGTestTesting ${ARG_LINK_LIBS}) + add_flangrt_dependent_libs(${test_name}${suffix}) if(NOT ARG_SLOW_TEST) add_dependencies(FlangRTUnitTests ${test_name}${suffix}) diff --git a/flang/docs/OpenMPSupport.md b/flang/docs/OpenMPSupport.md index c9f19c37fd7fa..81f5f9f6dee5b 100644 --- a/flang/docs/OpenMPSupport.md +++ b/flang/docs/OpenMPSupport.md @@ -41,7 +41,7 @@ Note : No distinction is made between the support in Parser/Semantics, MLIR, Low | target construct | P | device clause not supported | | target update construct | P | device clause not supported | | declare target directive | P | | -| teams construct | P | reduction clause not supported | +| teams construct | Y | | | distribute construct | P | dist_schedule clause not supported | | distribute simd construct | P | dist_schedule and linear clauses are not supported | | distribute parallel loop construct | P | dist_schedule clause not supported | @@ -51,15 +51,15 @@ Note : No distinction is made between the support in Parser/Semantics, MLIR, Low | atomic construct extensions | Y | | | cancel construct | Y | | | cancellation point construct | Y | | -| parallel do simd construct | P | linear clause is not supported | -| target teams construct | P | device and reduction clauses are not supported | -| teams distribute construct | P | reduction and dist_schedule clauses not supported | -| teams distribute simd construct | P | reduction, dist_schedule and linear clauses are not supported | -| target teams distribute construct | P | device, reduction and dist_schedule clauses are not supported | -| teams distribute parallel loop construct | P | reduction and dist_schedule clauses are not supported | -| target teams distribute parallel loop construct | P | device, reduction and dist_schedule clauses are not supported | -| teams distribute parallel loop simd construct | P | reduction, dist_schedule, and linear clauses are not supported | -| target teams distribute parallel loop simd construct | P | device, reduction, dist_schedule and linear clauses are not supported | +| parallel do simd construct | P | linear clause not supported | +| target teams construct | P | device clause not supported | +| teams distribute construct | P | dist_schedule clause not supported | +| teams distribute simd construct | P | dist_schedule and linear clauses are not supported | +| target teams distribute construct | P | device and dist_schedule clauses are not supported | +| teams distribute parallel loop construct | P | dist_schedule clause not supported | +| target teams distribute parallel loop construct | P | device and dist_schedule clauses are not supported | +| teams distribute parallel loop simd construct | P | dist_schedule and linear clauses are not supported | +| target teams distribute parallel loop simd construct | P | device, dist_schedule and linear clauses are not supported | ## Extensions ### ATOMIC construct diff --git a/flang/include/flang/Lower/ConvertType.h b/flang/include/flang/Lower/ConvertType.h index 179a682584046..3c726595c0f76 100644 --- a/flang/include/flang/Lower/ConvertType.h +++ b/flang/include/flang/Lower/ConvertType.h @@ -118,6 +118,9 @@ class ComponentReverseIterator { /// Advance iterator to the last components of the current type parent. const Fortran::semantics::DerivedTypeSpec &advanceToParentType(); + /// Get the parent component symbol for the current type. + const Fortran::semantics::Symbol *getParentComponent() const; + private: void setCurrentType(const Fortran::semantics::DerivedTypeSpec &derived); const Fortran::semantics::DerivedTypeSpec *currentParentType = nullptr; diff --git a/flang/include/flang/Lower/Support/ReductionProcessor.h b/flang/include/flang/Lower/Support/ReductionProcessor.h index 72d8a0096f511..0b49049d43ed2 100644 --- a/flang/include/flang/Lower/Support/ReductionProcessor.h +++ b/flang/include/flang/Lower/Support/ReductionProcessor.h @@ -124,7 +124,7 @@ class ReductionProcessor { /// Creates a reduction declaration and associates it with an OpenMP block /// directive. template - static void processReductionArguments( + static bool processReductionArguments( mlir::Location currentLocation, lower::AbstractConverter &converter, const RedOperatorListTy &redOperatorList, llvm::SmallVectorImpl &reductionVars, diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 33c1f1e7a3c3a..2105fc14b0a6f 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2123,9 +2123,10 @@ class FirConverter : public Fortran::lower::AbstractConverter { llvm::SmallVector reduceVars; Fortran::lower::omp::ReductionProcessor rp; - rp.processReductionArguments( + bool result = rp.processReductionArguments( toLocation(), *this, info.reduceOperatorList, reduceVars, reduceVarByRef, reductionDeclSymbols, info.reduceSymList); + assert(result && "Failed to process `do concurrent` reductions"); doConcurrentLoopOp.getReduceVarsMutable().assign(reduceVars); doConcurrentLoopOp.setReduceSymsAttr( @@ -5504,10 +5505,34 @@ class FirConverter : public Fortran::lower::AbstractConverter { void genFIR(const Fortran::parser::AssignStmt &stmt) { const Fortran::semantics::Symbol &symbol = *std::get(stmt.t).symbol; + mlir::Location loc = toLocation(); + mlir::Type symbolType = genType(symbol); + mlir::Value addr = getSymbolAddress(symbol); + + // Handle the case where the assigned variable is declared as a pointer + if (auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(symbolType)) { + if (auto ptrType = mlir::dyn_cast(eleTy)) { + symbolType = ptrType.getEleTy(); + } else { + symbolType = eleTy; + } + } else if (auto ptrType = mlir::dyn_cast(symbolType)) { + symbolType = ptrType.getEleTy(); + } + mlir::Value labelValue = builder->createIntegerConstant( - loc, genType(symbol), std::get(stmt.t)); - builder->create(loc, labelValue, getSymbolAddress(symbol)); + loc, symbolType, std::get(stmt.t)); + + // If the address points to a boxed pointer, we need to dereference it + if (auto refType = mlir::dyn_cast(addr.getType())) { + if (auto boxType = mlir::dyn_cast(refType.getEleTy())) { + mlir::Value boxValue = builder->create(loc, addr); + addr = builder->create(loc, boxValue); + } + } + + builder->create(loc, labelValue, addr); } void genFIR(const Fortran::parser::FormatStmt &) { diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 9689f920840fb..906a689821882 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -1848,8 +1848,15 @@ class HlfirBuilder { for (Fortran::lower::ComponentReverseIterator compIterator( ctor.result().derivedTypeSpec()); !compIterator.lookup(compSym.name());) { - const auto &parentType = compIterator.advanceToParentType(); - llvm::StringRef parentName = toStringRef(parentType.name()); + // Private parent components have mangled names. Get the name from the + // parent symbol. + const Fortran::semantics::Symbol *parentCompSym = + compIterator.getParentComponent(); + assert(parentCompSym && "failed to get parent component symbol"); + std::string parentName = + converter.getRecordTypeFieldName(*parentCompSym); + // Advance the iterator, but don't use its return value. + compIterator.advanceToParentType(); auto baseRecTy = mlir::cast( hlfir::getFortranElementType(currentParent.getType())); auto parentCompType = baseRecTy.getType(parentName); diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp index 7a2e8e5095186..0fde61465fb85 100644 --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -669,6 +669,18 @@ Fortran::lower::ComponentReverseIterator::advanceToParentType() { return *currentParentType; } +const Fortran::semantics::Symbol * +Fortran::lower::ComponentReverseIterator::getParentComponent() const { + if (!currentTypeDetails->GetParentComponentName()) + return nullptr; + const Fortran::semantics::Scope *scope = currentParentType->GetScope(); + auto parentComp = + DEREF(scope).find(currentTypeDetails->GetParentComponentName().value()); + if (parentComp == scope->cend()) + return nullptr; + return &*parentComp->second; +} + void Fortran::lower::ComponentReverseIterator::setCurrentType( const Fortran::semantics::DerivedTypeSpec &derived) { currentParentType = &derived; diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 63a612d7ead61..d64449373fca2 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -464,8 +464,10 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, fir::BoxType boxTy = fir::BoxType::get(fir::PointerType::get(converter.genType(s))); auto descFunc = [&](fir::FirOpBuilder &b) { + bool couldBeInEquivalence = + Fortran::semantics::FindEquivalenceSet(s) != nullptr; auto box = Fortran::lower::genInitialDataTarget( - converter, loc, boxTy, *expr, /*couldBeInEquivalence=*/true); + converter, loc, boxTy, *expr, couldBeInEquivalence); b.create(loc, box); }; builder.createGlobalConstant(loc, boxTy, mangleName, descFunc, linkOnce); diff --git a/flang/lib/Lower/Mangler.cpp b/flang/lib/Lower/Mangler.cpp index 1333e3fe349d1..e1ae86a1b5bb2 100644 --- a/flang/lib/Lower/Mangler.cpp +++ b/flang/lib/Lower/Mangler.cpp @@ -224,8 +224,18 @@ std::string Fortran::lower::mangle::mangleName( assert(paramExpr && "derived type kind param not explicit"); std::optional init = Fortran::evaluate::ToInt64(paramValue->GetExplicit()); - assert(init && "derived type kind param is not constant"); - kinds.emplace_back(*init); + // TODO: put the assertion check back when parametrized derived types + // are supported: + // assert(init && "derived type kind param is not constant"); + // + // The init parameter above will require a FoldingContext for proper + // expression evaluation to an integer constant, otherwise the + // compiler may crash here (see example in issue #127424). + if (!init) { + TODO_NOLOC("parameterized derived types"); + } else { + kinds.emplace_back(*init); + } } } return fir::NameUniquer::doType(modules, procs, blockId, symbolName, kinds); diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 74087d42a8e6e..40f735c33cc3c 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -1116,11 +1116,12 @@ bool ClauseProcessor::processInReduction( collectReductionSyms(clause, inReductionSyms); ReductionProcessor rp; - rp.processReductionArguments( - currentLocation, converter, - std::get(clause.t), - inReductionVars, inReduceVarByRef, inReductionDeclSymbols, - inReductionSyms); + if (!rp.processReductionArguments( + currentLocation, converter, + std::get(clause.t), + inReductionVars, inReduceVarByRef, inReductionDeclSymbols, + inReductionSyms)) + inReductionSyms.clear(); // Copy local lists into the output. llvm::copy(inReductionVars, std::back_inserter(result.inReductionVars)); @@ -1461,10 +1462,12 @@ bool ClauseProcessor::processReduction( } ReductionProcessor rp; - rp.processReductionArguments( - currentLocation, converter, - std::get(clause.t), - reductionVars, reduceVarByRef, reductionDeclSymbols, reductionSyms); + if (!rp.processReductionArguments( + currentLocation, converter, + std::get(clause.t), + reductionVars, reduceVarByRef, reductionDeclSymbols, + reductionSyms)) + reductionSyms.clear(); // Copy local lists into the output. llvm::copy(reductionVars, std::back_inserter(result.reductionVars)); llvm::copy(reduceVarByRef, std::back_inserter(result.reductionByref)); @@ -1486,11 +1489,12 @@ bool ClauseProcessor::processTaskReduction( collectReductionSyms(clause, taskReductionSyms); ReductionProcessor rp; - rp.processReductionArguments( - currentLocation, converter, - std::get(clause.t), - taskReductionVars, taskReduceVarByRef, taskReductionDeclSymbols, - taskReductionSyms); + if (!rp.processReductionArguments( + currentLocation, converter, + std::get(clause.t), + taskReductionVars, taskReduceVarByRef, taskReductionDeclSymbols, + taskReductionSyms)) + taskReductionSyms.clear(); // Copy local lists into the output. llvm::copy(taskReductionVars, std::back_inserter(result.taskReductionVars)); diff --git a/flang/lib/Lower/Support/ReductionProcessor.cpp b/flang/lib/Lower/Support/ReductionProcessor.cpp index c0be1e229f825..f58a103b03479 100644 --- a/flang/lib/Lower/Support/ReductionProcessor.cpp +++ b/flang/lib/Lower/Support/ReductionProcessor.cpp @@ -39,7 +39,7 @@ namespace lower { namespace omp { // explicit template declarations -template void ReductionProcessor::processReductionArguments< +template bool ReductionProcessor::processReductionArguments< mlir::omp::DeclareReductionOp, omp::clause::ReductionOperatorList>( mlir::Location currentLocation, lower::AbstractConverter &converter, const omp::clause::ReductionOperatorList &redOperatorList, @@ -48,7 +48,7 @@ template void ReductionProcessor::processReductionArguments< llvm::SmallVectorImpl &reductionDeclSymbols, const llvm::SmallVectorImpl &reductionSymbols); -template void ReductionProcessor::processReductionArguments< +template bool ReductionProcessor::processReductionArguments< fir::DeclareReductionOp, llvm::SmallVector>( mlir::Location currentLocation, lower::AbstractConverter &converter, const llvm::SmallVector &redOperatorList, @@ -606,7 +606,7 @@ static bool doReductionByRef(mlir::Value reductionVar) { } template -void ReductionProcessor::processReductionArguments( +bool ReductionProcessor::processReductionArguments( mlir::Location currentLocation, lower::AbstractConverter &converter, const RedOperatorListTy &redOperatorList, llvm::SmallVectorImpl &reductionVars, @@ -626,10 +626,10 @@ void ReductionProcessor::processReductionArguments( std::get_if(&redOperator.u)) { if (!ReductionProcessor::supportedIntrinsicProcReduction( *reductionIntrinsic)) { - return; + return false; } } else { - return; + return false; } } } @@ -764,6 +764,8 @@ void ReductionProcessor::processReductionArguments( if (isDoConcurrent) builder.restoreInsertionPoint(dcIP); + + return true; } const semantics::SourceName diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 2425265e196c6..783aef18fb894 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -16,7 +16,6 @@ #include "flang/Common/idioms.h" #include "flang/Common/indirection.h" #include "flang/Common/visit.h" -#include "flang/Evaluate/shape.h" #include "flang/Evaluate/tools.h" #include "flang/Evaluate/type.h" #include "flang/Parser/char-block.h" @@ -4117,21 +4116,26 @@ void OmpStructureChecker::CheckArraySection( // Detect this by looking for array accesses on character variables which are // not arrays. bool isSubstring{false}; - evaluate::ExpressionAnalyzer ea{context_}; - if (MaybeExpr expr = ea.Analyze(arrayElement.base)) { - std::optional shape = evaluate::GetShape(expr); - // Not an array: rank 0 - if (shape && shape->size() == 0) { - if (std::optional type = expr->GetType()) { - if (type->category() == evaluate::TypeCategory::Character) { - // Substrings are explicitly denied by the standard [6.0:163:9-11]. - // This is supported as an extension. This restriction was added in - // OpenMP 5.2. - isSubstring = true; - context_.Say(GetContext().clauseSource, - "The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2."_port_en_US); - } else { - llvm_unreachable("Array indexing on a variable that isn't an array"); + // Cannot analyze a base of an assumed-size array on its own. If we know + // this is an array (assumed-size or not) we can ignore it, since we're + // looking for strings. + if (!IsAssumedSizeArray(*name.symbol)) { + evaluate::ExpressionAnalyzer ea{context_}; + if (MaybeExpr expr = ea.Analyze(arrayElement.base)) { + if (expr->Rank() == 0) { + // Not an array: rank 0 + if (std::optional type = expr->GetType()) { + if (type->category() == evaluate::TypeCategory::Character) { + // Substrings are explicitly denied by the standard [6.0:163:9-11]. + // This is supported as an extension. This restriction was added in + // OpenMP 5.2. + isSubstring = true; + context_.Say(GetContext().clauseSource, + "The use of substrings in OpenMP argument lists has been disallowed since OpenMP 5.2."_port_en_US); + } else { + llvm_unreachable( + "Array indexing on a variable that isn't an array"); + } } } } diff --git a/flang/test/Driver/loop-interchange.f90 b/flang/test/Driver/loop-interchange.f90 index 5d3ec71c59874..1e5a11902709c 100644 --- a/flang/test/Driver/loop-interchange.f90 +++ b/flang/test/Driver/loop-interchange.f90 @@ -2,9 +2,9 @@ ! RUN: %flang -### -S -fno-loop-interchange %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s ! RUN: %flang -### -S -O0 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s ! RUN: %flang -### -S -O1 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s -! RUN: %flang -### -S -O2 %s 2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE %s -! RUN: %flang -### -S -O3 %s 2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE %s -! RUN: %flang -### -S -Os %s 2>&1 | FileCheck -check-prefix=CHECK-LOOP-INTERCHANGE %s +! RUN: %flang -### -S -O2 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s +! RUN: %flang -### -S -O3 %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s +! RUN: %flang -### -S -Os %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s ! RUN: %flang -### -S -Oz %s 2>&1 | FileCheck -check-prefix=CHECK-NO-LOOP-INTERCHANGE %s ! CHECK-LOOP-INTERCHANGE: "-floop-interchange" ! CHECK-NO-LOOP-INTERCHANGE-NOT: "-floop-interchange" diff --git a/flang/test/Driver/target-cpu-features.f90 b/flang/test/Driver/target-cpu-features.f90 index 5a3fd0d838002..e7da964184c85 100644 --- a/flang/test/Driver/target-cpu-features.f90 +++ b/flang/test/Driver/target-cpu-features.f90 @@ -44,6 +44,10 @@ ! RUN: %flang --target=loongarch64-linux-gnu -c %s -### 2>&1 \ ! RUN: | FileCheck %s -check-prefix=CHECK-LOONGARCH64 +! RUN: %flang --target=sparc64-linux-gnu -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS +! RUN: %flang --target=sparc64-freebsd -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS +! RUN: %flang --target=sparc64-openbsd -c -### %s 2>&1 | FileCheck %s -check-prefix=CHECK-SPARC-VIS + ! CHECK-A57: "-fc1" "-triple" "aarch64-unknown-linux-gnu" ! CHECK-A57-SAME: "-target-cpu" "cortex-a57" ! CHECK-A57-SAME: "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2 @@ -92,3 +96,6 @@ ! CHECK-LOONGARCH64: "-fc1" "-triple" "loongarch64-unknown-linux-gnu" ! CHECK-LOONGARCH64-SAME: "-target-cpu" "loongarch64" "-target-feature" "+lsx" "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+ual" + +! CHECK-SPARC-VIS: "-fc1" "-triple" "sparc64-{{[^"]+}}" +! CHECK-SPARC-VIS-SAME: "-target-feature" "+vis" diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-non-intrinsic.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-non-intrinsic.f90 new file mode 100644 index 0000000000000..70b2ae1111a50 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-non-intrinsic.f90 @@ -0,0 +1,25 @@ +! Tests reduction processor behavior when a reduction symbol is not supported. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +subroutine foo + implicit none + integer :: k, i + + interface max + function max(m1,m2) + integer :: m1, m2 + end function + end interface + + !$omp do reduction (max: k) + do i=1,10 + end do + !$omp end do +end + +! Verify that unsupported reduction is ignored. +! CHECK: omp.wsloop +! CHECK-SAME: private(@{{[^[:space:]]+}} %{{[^[:space:]]+}} +! CHECK-SAME: -> %{{[^[:space:]]+}} : !{{[^[:space:]]+}}) { +! CHECK: } diff --git a/flang/test/Lower/assign-statement.f90 b/flang/test/Lower/assign-statement.f90 new file mode 100644 index 0000000000000..342355bf469c8 --- /dev/null +++ b/flang/test/Lower/assign-statement.f90 @@ -0,0 +1,12 @@ +! RUN: bbc -emit-fir -o - %s | FileCheck %s + + ! CHECK-LABEL: func @_QQmain + program main + integer :: ip + pointer :: ip + + allocate(ip) + assign 10 to ip + ! CHECK: fir.store %c10_i32 to %11 : !fir.ptr + 10 return + end program main diff --git a/flang/test/Lower/derived-type-private.f90 b/flang/test/Lower/derived-type-private.f90 new file mode 100644 index 0000000000000..8edcdeedad8b2 --- /dev/null +++ b/flang/test/Lower/derived-type-private.f90 @@ -0,0 +1,29 @@ +! Test lowering of derived type with private attribute +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s + +program main + call test02() + print *,"pass" +end program main + +module mod2 + type,private:: tt + integer :: ip = 1 + end type tt + type,extends(tt):: ty1 + ! CHECK: fir.global @_QMmod2Estr : !fir.type<_QMmod2Tty1{_QMmod2Tty1.tt:!fir.type<_QMmod2Ttt{ip:i32}>,i1:i32,i1p:!fir.type<_QMmod2Ttt{ip:i32}>,i1a:!fir.box>>}> + integer :: i1 = 1 + type(tt) :: i1p = tt(2) + integer,allocatable :: i1a(:) + end type ty1 + type(ty1) :: str +end module mod2 + +subroutine test02() + use mod2 + integer,allocatable :: ia(:) + allocate(ia(10)) + ia=2 + str=ty1(i1a=ia) + if (str%i1.ne.1) print *,'ng' +end subroutine test02 diff --git a/flang/test/Lower/equivalence-3.f b/flang/test/Lower/equivalence-3.f new file mode 100644 index 0000000000000..19f8880189f0c --- /dev/null +++ b/flang/test/Lower/equivalence-3.f @@ -0,0 +1,19 @@ +! RUN: bbc -emit-fir -o - %s | FileCheck %s + + ! CHECK-LABEL: func @_QQmain + program main + real a1,a2 + equivalence (a1,a2) + ! A fir.alloca should never appear in a global constant initialization. + ! CHECK: fir.global linkonce @_QFEx1.desc constant : !fir.box>> + ! CHECK: arith.constant 5 : index + ! CHECK:fir.address_of(@_QFEx1) : !fir.ref> + ! CHECK: fir.shape %c5 : (index) -> !fir.shape<1> + ! CHECK: fir.declare %0(%1) {uniq_name = "_QFEx1"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + ! CHECK: fir.embox %2(%1) : (!fir.ref>, !fir.shape<1>) -> !fir.box> + ! CHECK: fir.rebox %3 : (!fir.box>) -> !fir.box>> + ! CHECK: fir.has_value %4 : !fir.box>> + real*8 x1(5) + namelist /y1/x1 + read (5,y1) + end diff --git a/flang/test/Lower/parametrized-derived-types.f90 b/flang/test/Lower/parametrized-derived-types.f90 new file mode 100644 index 0000000000000..97a40c9169d2b --- /dev/null +++ b/flang/test/Lower/parametrized-derived-types.f90 @@ -0,0 +1,19 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! XFAIL: * +program main + TYPE ty(k1,k2) + INTEGER ,KIND::k1,k2=5 + INTEGER::arr(k1:k2)=10 + CHARACTER(LEN=k2)::CHARACTER + END TYPE ty + TYPE,EXTENDS(ty)::ty1(k3) + INTEGER,KIND ::k3=4 + TYPE(ty(2,k3+1))::cmp_ty = ty(2,k3+1)(55,'HI') + END TYPE ty1 + TYPE ty2(l1, l2) + !ERROR: not yet implemented: parameterized derived types + INTEGER,LEN ::l1,l2 + TYPE(ty1(2,5)), ALLOCATABLE::ty1_cmp(:) + END TYPE ty2 + TYPE(ty2(4,8)) ::ty2_obj +end program main diff --git a/flang/test/Semantics/OpenMP/assumed-size-array.f90 b/flang/test/Semantics/OpenMP/assumed-size-array.f90 new file mode 100644 index 0000000000000..6e36db178dc8e --- /dev/null +++ b/flang/test/Semantics/OpenMP/assumed-size-array.f90 @@ -0,0 +1,25 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +! This should compile without errors. Check for a symptom of a reasonable +! output. + +!CHECK: omp.task depend + +subroutine omp_task_depend_reproducer(work, myid, shift) + implicit none + integer, intent(in) :: myid, shift + real, intent(inout) :: work(*) + +!$omp parallel shared(work, myid, shift) + !$omp single + !$omp task depend(in:work(myid+shift-1)) depend(in:work(myid-1)) depend(out:work(myid)) + call dummy_kernel(work(myid)) + !$omp end task + !$omp end single +!$omp end parallel +contains + subroutine dummy_kernel(x) + real :: x + x = x + 1.0 + end subroutine dummy_kernel +end subroutine omp_task_depend_reproducer diff --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt index 469266cc81558..7516157731b5e 100644 --- a/flang/tools/bbc/CMakeLists.txt +++ b/flang/tools/bbc/CMakeLists.txt @@ -30,6 +30,11 @@ target_link_libraries(bbc PRIVATE flangFrontend flangPasses FlangOpenMPTransforms + FortranSupport + FortranParser + FortranEvaluate + FortranSemantics + FortranLower ) mlir_target_link_libraries(bbc PRIVATE @@ -37,9 +42,4 @@ mlir_target_link_libraries(bbc PRIVATE ${extension_libs} MLIRAffineToStandard MLIRSCFToControlFlow - FortranSupport - FortranParser - FortranEvaluate - FortranSemantics - FortranLower ) diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 2570d1a106d21..c98e2043464d9 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -84,9 +84,6 @@ else() endif() endif() -# Setup the paths where libclc runtimes should be stored. -set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) - if( EXISTS ${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR} ) message( WARNING "Using custom LLVM tools to build libclc: " "${LIBCLC_CUSTOM_LLVM_TOOLS_BINARY_DIR}, " @@ -164,14 +161,34 @@ endif() list( SORT LIBCLC_TARGETS_TO_BUILD ) +# Construct LLVM version define +set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MINOR}" ) + # This needs to be set before any target that needs it # We need to use LLVM_INCLUDE_DIRS here, because if we are linking to an # llvm build directory, this includes $src/llvm/include which is where all the # headers are not $build/include/ which is what LLVM_INCLUDE_DIR is set to. include_directories( ${LLVM_INCLUDE_DIRS} ) -# Configure prepare_builtins -add_subdirectory( utils ) +# Setup prepare_builtins tools +set(LLVM_LINK_COMPONENTS + BitReader + BitWriter + Core + IRReader + Support +) +if( LIBCLC_STANDALONE_BUILD ) + add_llvm_executable( prepare_builtins utils/prepare-builtins.cpp ) + set( prepare_builtins_exe prepare_builtins ) + set( prepare_builtins_target prepare_builtins ) +else() + add_llvm_utility( prepare_builtins utils/prepare-builtins.cpp ) + setup_host_tool( prepare_builtins PREPARE_BUILTINS prepare_builtins_exe prepare_builtins_target ) +endif() +target_compile_definitions( prepare_builtins PRIVATE ${LLVM_VERSION_DEFINE} ) +# These were not properly reported in early LLVM and we don't need them +target_compile_options( prepare_builtins PRIVATE -fno-rtti -fno-exceptions ) # Setup arch devices set( r600--_devices cedar cypress barts cayman ) diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake index 056706ee629cd..597bb642655e4 100644 --- a/libclc/cmake/modules/AddLibclc.cmake +++ b/libclc/cmake/modules/AddLibclc.cmake @@ -120,14 +120,14 @@ function(link_bc) endif() add_custom_command( - OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc - COMMAND ${llvm-link_exe} ${link_flags} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc ${LINK_INPUT_ARG} + OUTPUT ${ARG_TARGET}.bc + COMMAND ${llvm-link_exe} ${link_flags} -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG} DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE} ) - add_custom_target( ${ARG_TARGET} ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc ) + add_custom_target( ${ARG_TARGET} ALL DEPENDS ${ARG_TARGET}.bc ) set_target_properties( ${ARG_TARGET} PROPERTIES - TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.bc + TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${ARG_TARGET}.bc FOLDER "libclc/Device IR/Linking" ) endfunction() @@ -356,98 +356,65 @@ function(add_libclc_builtin_set) set( builtins_link_lib $ ) - # For SPIR-V targets we diverage at this point and generate SPIR-V using the - # llvm-spirv tool. if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 ) - set( obj_suffix ${ARG_ARCH_SUFFIX}.spv ) - set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} ) - add_custom_command( OUTPUT ${libclc_builtins_lib} - COMMAND ${llvm-spirv_exe} ${spvflags} -o ${libclc_builtins_lib} ${builtins_link_lib} + set( spv_suffix ${ARG_ARCH_SUFFIX}.spv ) + add_custom_command( OUTPUT ${spv_suffix} + COMMAND ${llvm-spirv_exe} ${spvflags} -o ${spv_suffix} ${builtins_link_lib} DEPENDS ${llvm-spirv_target} ${builtins_link_lib} ${builtins_link_lib_tgt} ) - else() - # Non-SPIR-V targets add an extra step to optimize the bytecode - set( builtins_opt_lib_tgt builtins.opt.${ARG_ARCH_SUFFIX} ) + add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" ) + set_target_properties( "prepare-${spv_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix} + DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) - add_custom_command( OUTPUT ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc - COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc - ${builtins_link_lib} - DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt} - ) - add_custom_target( ${builtins_opt_lib_tgt} - ALL DEPENDS ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc - ) - set_target_properties( ${builtins_opt_lib_tgt} PROPERTIES - TARGET_FILE ${LIBCLC_ARCH_OBJFILE_DIR}/${builtins_opt_lib_tgt}.bc - FOLDER "libclc/Device IR/Opt" - ) - - set( builtins_opt_lib $ ) - - set( obj_suffix ${ARG_ARCH_SUFFIX}.bc ) - set( libclc_builtins_lib ${LIBCLC_OUTPUT_LIBRARY_DIR}/${obj_suffix} ) - add_custom_command( OUTPUT ${libclc_builtins_lib} - COMMAND ${prepare_builtins_exe} -o ${libclc_builtins_lib} ${builtins_opt_lib} - DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} - ) + return() endif() - # Add a 'prepare' target - add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${libclc_builtins_lib} ) - set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" ) - - # Also add a 'prepare' target for the triple. Since a triple may have - # multiple devices, ensure we only try to create the triple target once. The - # triple's target will build all of the bytecode for its constituent devices. - if( NOT TARGET prepare-${ARG_TRIPLE} ) - add_custom_target( prepare-${ARG_TRIPLE} ALL ) - endif() - add_dependencies( prepare-${ARG_TRIPLE} prepare-${obj_suffix} ) + set( builtins_opt_lib_tgt builtins.opt.${ARG_ARCH_SUFFIX} ) - install( - FILES ${libclc_builtins_lib} - DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" + # Add opt target + add_custom_command( OUTPUT ${builtins_opt_lib_tgt}.bc + COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${builtins_opt_lib_tgt}.bc + ${builtins_link_lib} + DEPENDS ${opt_target} ${builtins_link_lib} ${builtins_link_lib_tgt} + ) + add_custom_target( ${builtins_opt_lib_tgt} + ALL DEPENDS ${builtins_opt_lib_tgt}.bc + ) + set_target_properties( ${builtins_opt_lib_tgt} PROPERTIES + TARGET_FILE ${CMAKE_CURRENT_BINARY_DIR}/${builtins_opt_lib_tgt}.bc + FOLDER "libclc/Device IR/Opt" ) - # SPIR-V targets can exit early here - if( ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64 ) - return() - endif() + set( builtins_opt_lib $ ) - # Add a test for whether or not the libraries contain unresolved calls which - # would usually indicate a build problem. Note that we don't perform this - # test for all libclc targets: - # * nvptx-- targets don't include workitem builtins - # * clspv targets don't include all OpenCL builtins + # Add prepare target + set( obj_suffix ${ARG_ARCH_SUFFIX}.bc ) + add_custom_command( OUTPUT ${obj_suffix} + COMMAND ${prepare_builtins_exe} -o ${obj_suffix} ${builtins_opt_lib} + DEPENDS ${builtins_opt_lib} ${builtins_opt_lib_tgt} ${prepare_builtins_target} ) + add_custom_target( prepare-${obj_suffix} ALL DEPENDS ${obj_suffix} ) + set_target_properties( "prepare-${obj_suffix}" PROPERTIES FOLDER "libclc/Device IR/Prepare" ) + + # nvptx-- targets don't include workitem builtins, and clspv targets don't + # include all OpenCL builtins if( NOT ARG_ARCH MATCHES "^(nvptx|clspv)(64)?$" ) add_test( NAME external-calls-${obj_suffix} - COMMAND ./check_external_calls.sh ${libclc_builtins_lib} ${LLVM_TOOLS_BINARY_DIR} + COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() - if(CMAKE_HOST_UNIX OR LLVM_USE_SYMLINKS) - set(LIBCLC_LINK_OR_COPY create_symlink) - else() - set(LIBCLC_LINK_OR_COPY copy) - endif() - - foreach( a IN LISTS ARG_ALIASES ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + foreach( a ${ARG_ALIASES} ) set( alias_suffix "${a}-${ARG_TRIPLE}.bc" ) add_custom_command( - OUTPUT ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} - COMMAND ${CMAKE_COMMAND} -E ${LIBCLC_LINK_OR_COPY} ${libclc_builtins_lib} ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} - DEPENDS prepare-${obj_suffix} - ) - add_custom_target( alias-${alias_suffix} ALL - DEPENDS ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} - ) - set_target_properties( alias-${alias_suffix} - PROPERTIES FOLDER "libclc/Device IR/Aliases" - ) - install( - FILES ${LIBCLC_OUTPUT_LIBRARY_DIR}/${alias_suffix} - DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" - ) + OUTPUT ${alias_suffix} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix} + DEPENDS prepare-${obj_suffix} ) + add_custom_target( alias-${alias_suffix} ALL DEPENDS ${alias_suffix} ) + set_target_properties( alias-${alias_suffix} PROPERTIES FOLDER "libclc/Device IR/Aliases" ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} + DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) endforeach( a ) endfunction(add_libclc_builtin_set) diff --git a/libclc/utils/CMakeLists.txt b/libclc/utils/CMakeLists.txt deleted file mode 100644 index ea1d9e9c8ef5f..0000000000000 --- a/libclc/utils/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Construct LLVM version define -set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MINOR}" ) - -# Setup prepare_builtins tools -set( LLVM_LINK_COMPONENTS - BitReader - BitWriter - Core - IRReader - Support -) - -if( LIBCLC_STANDALONE_BUILD ) - add_llvm_executable( prepare_builtins prepare-builtins.cpp ) - set( prepare_builtins_exe prepare_builtins ) - set( prepare_builtins_target prepare_builtins ) -else() - add_llvm_utility( prepare_builtins prepare-builtins.cpp ) - setup_host_tool( prepare_builtins PREPARE_BUILTINS prepare_builtins_exe prepare_builtins_target ) -endif() - -target_compile_definitions( prepare_builtins PRIVATE ${LLVM_VERSION_DEFINE} ) -# These were not properly reported in early LLVM and we don't need them -target_compile_options( prepare_builtins PRIVATE -fno-rtti -fno-exceptions ) diff --git a/libcxx/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake b/libcxx/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake new file mode 100644 index 0000000000000..c843c02977a87 --- /dev/null +++ b/libcxx/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake @@ -0,0 +1,2 @@ +set(LIBCXX_HARDENING_MODE "extensive" CACHE STRING "") +set(LIBCXX_TEST_PARAMS "assertion_semantic=observe" CACHE STRING "") diff --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst index 17808841bd9ec..1cdb3605c38ab 100644 --- a/libcxx/docs/Hardening.rst +++ b/libcxx/docs/Hardening.rst @@ -39,6 +39,8 @@ modes are: Enabling hardening has no impact on the ABI. +.. _notes-for-users: + Notes for users --------------- @@ -72,6 +74,10 @@ to control the level by passing **one** of the following options to the compiler pre-built components. Most libc++ code is header-based, so a user-provided value for ``_LIBCPP_HARDENING_MODE`` will be mostly respected. +In some cases, users might want to override the assertion semantic used by the +library. This can be done similarly to setting the hardening mode; please refer +to the :ref:`relevant section `. + Notes for vendors ----------------- @@ -260,6 +266,68 @@ output. This is less secure and increases the size of the binary (among other things, it has to store the error message strings) but makes the failure easier to debug. It also allows testing the error messages in our test suite. +This default behavior can be customized by users via :ref:`assertion semantics +`; it can also be completely overridden by vendors by +providing a :ref:`custom assertion failure handler +`. + +.. _assertion-semantics: + +Assertion semantics +------------------- + +.. warning:: + + Assertion semantics are currently an experimental feature. + +.. note:: + + Assertion semantics are not available in the C++03 mode. + +What happens when an assertion fails depends on the assertion semantic being +used. Four assertion semantics are available, based on C++26 Contracts +evaluation semantics: + +- ``ignore`` evaluates the assertion but has no effect if it fails (note that it + differs from the Contracts ``ignore`` semantic which would not evaluate + the assertion at all); +- ``observe`` logs an error (indicating, if possible on the platform, that the + error is fatal) but continues execution; +- ``quick-enforce`` terminates the program as fast as possible via a trap + instruction. It is the default semantic for the production modes (``fast`` and + ``extensive``); +- ``enforce`` logs an error and then terminates the program. It is the default + semantic for the ``debug`` mode. + +Notes: + +- Continuing execution after a hardening check fails results in undefined + behavior; the ``observe`` semantic is meant to make adopting hardening easier + but should not be used outside of the adoption period; +- C++26 wording for Library Hardening precludes a conforming Hardened + implementation from using the Contracts ``ignore`` semantic when evaluating + hardened preconditions in the Library. Libc++ allows using this semantic for + hardened preconditions, but please be aware that using ``ignore`` does not + produce a conforming "Hardened" implementation, unlike the other semantics + above. + +The default assertion semantics are as follows: + +- ``fast``: ``quick-enforce``; +- ``extensive``: ``quick-enforce``; +- ``debug``: ``enforce``. + +The default assertion semantics can be overridden by passing **one** of the +following options to the compiler: + +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_IGNORE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_OBSERVE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE`` +- ``-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE`` + +All the :ref:`same notes ` apply to setting this macro as for +setting ``_LIBCPP_HARDENING_MODE``. + .. _override-assertion-handler: Overriding the assertion failure handler diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index 6f18b61284f49..2b1aa28b62090 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -10,7 +10,7 @@ Written by the `Libc++ Team `_ .. warning:: - These are in-progress notes for the upcoming libc++ 20.0.0 release. + These are in-progress notes for the upcoming libc++ 21.0.0 release. Release notes for previous releases can be found on `the Download Page `_. @@ -18,7 +18,7 @@ Introduction ============ This document contains the release notes for the libc++ C++ Standard Library, -part of the LLVM Compiler Infrastructure, release 20.0.0. Here we describe the +part of the LLVM Compiler Infrastructure, release 21.0.0. Here we describe the status of libc++ in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see `the LLVM documentation `_. All LLVM releases may @@ -53,6 +53,7 @@ Implemented Papers - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) - P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github `__) +- P3379R0: Constrain ``std::expected`` equality operators (`Github `__) Improvements and New Features ----------------------------- @@ -88,6 +89,12 @@ Improvements and New Features - ``ctype::tolower`` and ``ctype::toupper`` have been optimized, resulting in a 2x performance improvement. +- As an experimental feature, Hardening now supports assertion semantics that allow customizing how a hardening + assertion failure is handled. The four available semantics, modeled on C++26 Contracts, are ``ignore``, ``observe``, + ``quick-enforce`` and ``enforce``. The ``observe`` semantic is intended to make it easier to adopt Hardening in + production but should not be used outside of this scenario. Please refer to the :ref:`Hardening documentation + ` for details. + Deprecations and Removals ------------------------- @@ -140,6 +147,21 @@ ABI Affecting Changes comparison between shared libraries, since all RTTI has the correct visibility now. There is no behaviour change on Clang. +- LLVM 20 contained an ABI break that can result in the size of ``std::unordered_{map,set,multimap,multiset}`` and ``std::deque`` changing when used with an allocator type that is empty and contains a base class that is the same across rebound allocator instantiations (e.g. ``Allocator`` and ``Allocator`` are both empty and contain the same base class). + In addition, the layout of a user-defined type that: + + - contains one of the following containers: ``std::unordered_{map,set,multimap,multiset}``, ``std::deque``, ``std::map``, ``std::set``, ``std::multimap``, ``std::multiset``, ``std::list`` or ``std::vector``, and + - passes an empty allocator, comparator or hasher type to that container, and + - has a member of that same empty allocator, comparator or hasher type inside the enclosing struct, and + - that member is either marked with ``[[no_unique_address]]`` or optimized out via the EBO (empty base optimization) technique + + saw its size increase from LLVM 19 to LLVM 20. This was caused by the usage of ``[[no_unique_address]]`` within some of libc++'s containers in a way that allowed subtle interactions with enclosing objects. This is fixed in LLVM 21 when using the Clang compiler (returning to the LLVM 19 ABI), however that implies an ABI break from LLVM 20 to LLVM 21. + + Furthermore, fixing this causes a slight regression to constant evaluation support in ``std::unique_ptr``. Specifically, constant evaluation will now fail when the deleter relies on being value-initialized for constant-evaluation admissibility. If a default-initialized deleter can be used during constant evaluation, or if the default constructor is non-trivial, the ``unique_ptr`` is not affected by this regression. In particular, this regression does not impact any ``unique_ptr`` using the default deleter. + + Note that there is currently no way to realistically fix this ABI break on GCC, therefore GCC will remain on the ABI introduced in LLVM 19. That also means that Clang and GCC will have a slightly different ABI for the small subset of types listed above until we are able to apply the same fix we did with Clang on GCC. + + For more details see https://llvm.org/PR154146. Build System Changes -------------------- diff --git a/libcxx/docs/UserDocumentation.rst b/libcxx/docs/UserDocumentation.rst index 79f5908bdc6b6..415a599168374 100644 --- a/libcxx/docs/UserDocumentation.rst +++ b/libcxx/docs/UserDocumentation.rst @@ -72,6 +72,11 @@ when ``-fexperimental-library`` is passed: * ``std::chrono::tzdb`` and related time zone functionality * ```` +Additionally, assertion semantics are an experimental feature that can be used +to customize the behavior of Hardening (see :ref:`here `). +Assertion semantics mirror the evaluation semantics of C++26 Contracts but are +not a standard feature. + .. note:: Experimental libraries are experimental. * The contents of the ```` headers and the associated static diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 4f2a8dddad92c..9e9852de2a4c7 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -535,6 +535,7 @@ set(files __locale_dir/time.h __locale_dir/wbuffer_convert.h __locale_dir/wstring_convert.h + __log_hardening_failure __math/abs.h __math/copysign.h __math/error_functions.h @@ -873,6 +874,7 @@ set(files __type_traits/is_trivially_relocatable.h __type_traits/is_unbounded_array.h __type_traits/is_union.h + __type_traits/is_unqualified.h __type_traits/is_unsigned.h __type_traits/is_valid_expansion.h __type_traits/is_void.h diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h index 06cb5b8ce7057..8aa894e9228c6 100644 --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -860,6 +860,9 @@ __sort<__less&, long double*>(long double*, long double*, __less _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { + if (__first == __last) // log(0) is undefined, so don't try computing the depth + return; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; difference_type __depth_limit = 2 * std::__bit_log2(std::__to_unsigned_like(__last - __first)); diff --git a/libcxx/include/__assert b/libcxx/include/__assert index 90eaa6023587b..a9451daf47f2f 100644 --- a/libcxx/include/__assert +++ b/libcxx/include/__assert @@ -20,8 +20,8 @@ #define _LIBCPP_ASSERT(expression, message) \ (__builtin_expect(static_cast(expression), 1) \ ? (void)0 \ - : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \ - expression) " failed: " message "\n")) + : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING( \ + __LINE__) ": libc++ Hardening assertion " _LIBCPP_TOSTRING(expression) " failed: " message "\n")) // WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear // optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a diff --git a/libcxx/include/__bit/bit_log2.h b/libcxx/include/__bit/bit_log2.h index 8077cd91d6fd7..9ceeec1b2bc94 100644 --- a/libcxx/include/__bit/bit_log2.h +++ b/libcxx/include/__bit/bit_log2.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___BIT_BIT_LOG2_H #define _LIBCPP___BIT_BIT_LOG2_H +#include <__assert> #include <__bit/countl.h> #include <__config> #include <__type_traits/integer_traits.h> @@ -23,6 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __bit_log2(_Tp __t) _NOEXCEPT { static_assert(__is_unsigned_integer_v<_Tp>, "__bit_log2 requires an unsigned integer type"); + _LIBCPP_ASSERT_INTERNAL(__t != 0, "logarithm of 0 is undefined"); return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__t); } diff --git a/libcxx/include/__config b/libcxx/include/__config index d940461c30234..699e195da2e07 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -28,7 +28,7 @@ // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. // Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 210000 +# define _LIBCPP_VERSION 210108 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -38,11 +38,47 @@ # define _LIBCPP_FREESTANDING # endif +// NOLINTNEXTLINE(libcpp-cpp-version-check) +# if __cplusplus < 201103L +# define _LIBCPP_CXX03_LANG +# endif + +# if __has_feature(experimental_library) +# ifndef _LIBCPP_ENABLE_EXPERIMENTAL +# define _LIBCPP_ENABLE_EXPERIMENTAL +# endif +# endif + +// Incomplete features get their own specific disabling flags. This makes it +// easier to grep for target specific flags once the feature is complete. +# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 +# else +# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 +# endif + +# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY + // HARDENING { -// TODO: Remove in LLVM 21. We're making this an error to catch folks who might not have migrated. -# ifdef _LIBCPP_ENABLE_ASSERTIONS -# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE instead" +// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated. +// Since hardening went through several changes (many of which impacted user-facing macros), +// we're keeping these checks around for a bit longer than usual. Failure to properly configure +// hardening results in checks being dropped silently, which is a pretty big deal. +# if defined(_LIBCPP_ENABLE_ASSERTIONS) +# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_HARDENED_MODE) +# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_SAFE_MODE) +# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" +# endif +# if defined(_LIBCPP_ENABLE_DEBUG_MODE) +# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE= instead (see docs)" # endif // The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: @@ -147,16 +183,53 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif +// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts: +// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts +// `ignore` semantic which wouldn't evaluate the assertion at all); +// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution; +// - `quick-enforce` terminates the program as fast as possible (via trapping); +// - `enforce` logs an error and then terminates the program. +// +// Notes: +// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant +// to make adopting hardening easier but should not be used outside of this scenario; +// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts +// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for +// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened" +// implementation, unlike the other semantics above. +// clang-format off +# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1) +# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2) +# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3) +# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4) +// clang-format on + +// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics. +// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use +// `enforce` (i.e., log and abort). +# ifndef _LIBCPP_ASSERTION_SEMANTIC + +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE +# else +# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE +# endif + +# else +# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# error "Assertion semantics are an experimental feature." +# endif +# if defined(_LIBCPP_CXX03_LANG) +# error "Assertion semantics are not available in the C++03 mode." +# endif + +# endif // _LIBCPP_ASSERTION_SEMANTIC + // } HARDENING # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) -// NOLINTNEXTLINE(libcpp-cpp-version-check) -# if __cplusplus < 201103L -# define _LIBCPP_CXX03_LANG -# endif - # ifndef __has_constexpr_builtin # define __has_constexpr_builtin(x) 0 # endif @@ -190,24 +263,6 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_ABI_VCRUNTIME # endif -# if __has_feature(experimental_library) -# ifndef _LIBCPP_ENABLE_EXPERIMENTAL -# define _LIBCPP_ENABLE_EXPERIMENTAL -# endif -# endif - -// Incomplete features get their own specific disabling flags. This makes it -// easier to grep for target specific flags once the feature is complete. -# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY) -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1 -# else -# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0 -# endif - -# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY -# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY - # if defined(__MVS__) # include // for __NATIVE_ASCII_F # endif diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h index a75cd0a675339..3f758d97394f4 100644 --- a/libcxx/include/__configuration/abi.h +++ b/libcxx/include/__configuration/abi.h @@ -30,8 +30,20 @@ #elif _LIBCPP_ABI_FORCE_MICROSOFT # define _LIBCPP_ABI_MICROSOFT #else +// Windows uses the Microsoft ABI # if defined(_WIN32) && defined(_MSC_VER) # define _LIBCPP_ABI_MICROSOFT + +// 32-bit ARM uses the Itanium ABI with a few differences (array cookies, etc), +// and so does 64-bit ARM on Apple platforms. +# elif defined(__arm__) || (defined(__APPLE__) && defined(__aarch64__)) +# define _LIBCPP_ABI_ITANIUM_WITH_ARM_DIFFERENCES + +// Non-Apple 64-bit ARM uses the vanilla Itanium ABI +# elif defined(__aarch64__) +# define _LIBCPP_ABI_ITANIUM + +// We assume that other architectures also use the vanilla Itanium ABI too # else # define _LIBCPP_ABI_ITANIUM # endif diff --git a/libcxx/include/__cxx03/__config b/libcxx/include/__cxx03/__config index ef47327d96355..9b88a495055ee 100644 --- a/libcxx/include/__cxx03/__config +++ b/libcxx/include/__cxx03/__config @@ -152,6 +152,10 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \ _LIBCPP_HARDENING_MODE_DEBUG # endif +# ifdef _LIBCPP_ASSERTION_SEMANTIC +# error "Assertion semantics are not available in the C++03 mode." +# endif + // } HARDENING # define _LIBCPP_TOSTRING2(x) #x diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h index 489a6f00b8a3d..83bbf1b5e26c3 100644 --- a/libcxx/include/__functional/hash.h +++ b/libcxx/include/__functional/hash.h @@ -21,6 +21,7 @@ #include <__type_traits/is_enum.h> #include <__type_traits/is_floating_point.h> #include <__type_traits/is_integral.h> +#include <__type_traits/is_unqualified.h> #include <__type_traits/underlying_type.h> #include <__utility/pair.h> #include <__utility/swap.h> @@ -355,7 +356,8 @@ struct __hash_impl { }; template -struct __hash_impl<_Tp, __enable_if_t::value> > : __unary_function<_Tp, size_t> { +struct __hash_impl<_Tp, __enable_if_t::value && __is_unqualified_v<_Tp> > > + : __unary_function<_Tp, size_t> { _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { using type = __underlying_type_t<_Tp>; return hash()(static_cast(__v)); @@ -363,17 +365,21 @@ struct __hash_impl<_Tp, __enable_if_t::value> > : __unary_function< }; template -struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) <= sizeof(size_t))> > +struct __hash_impl< + _Tp, + __enable_if_t::value && __is_unqualified_v<_Tp> && (sizeof(_Tp) <= sizeof(size_t))> > : __unary_function<_Tp, size_t> { _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { return static_cast(__v); } }; template -struct __hash_impl<_Tp, __enable_if_t::value && (sizeof(_Tp) > sizeof(size_t))> > +struct __hash_impl<_Tp, + __enable_if_t::value && __is_unqualified_v<_Tp> && (sizeof(_Tp) > sizeof(size_t))> > : __scalar_hash<_Tp> {}; template -struct __hash_impl<_Tp, __enable_if_t::value> > : __scalar_hash<_Tp> { +struct __hash_impl<_Tp, __enable_if_t::value && __is_unqualified_v<_Tp> > > + : __scalar_hash<_Tp> { _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash if (__v == 0.0f) diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure new file mode 100644 index 0000000000000..d1805306f6b6e --- /dev/null +++ b/libcxx/include/__log_hardening_failure @@ -0,0 +1,42 @@ +// -*- 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 _LIBCPP___LOG_HARDENING_FAILURE +#define _LIBCPP___LOG_HARDENING_FAILURE + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental +// library. +#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This function should never be called directly from the code -- it should only be called through the +// `_LIBCPP_LOG_HARDENING_FAILURE` macro. +[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept; + +// _LIBCPP_LOG_HARDENING_FAILURE(message) +// +// This macro is used to log an error without terminating the program (as is the case for hardening failures if the +// `observe` assertion semantic is used). + +# if !defined(_LIBCPP_LOG_HARDENING_FAILURE) +# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message) +# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +#endif // _LIBCPP___LOG_HARDENING_FAILURE diff --git a/libcxx/include/__memory/array_cookie.h b/libcxx/include/__memory/array_cookie.h index 806a9e99ecafe..be59f365aa80c 100644 --- a/libcxx/include/__memory/array_cookie.h +++ b/libcxx/include/__memory/array_cookie.h @@ -13,6 +13,7 @@ #include <__config> #include <__configuration/abi.h> #include <__cstddef/size_t.h> +#include <__memory/addressof.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_trivially_destructible.h> #include <__type_traits/negation.h> @@ -26,14 +27,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Trait representing whether a type requires an array cookie at the start of its allocation when // allocated as `new T[n]` and deallocated as `delete[] array`. // -// Under the Itanium C++ ABI [1], we know that an array cookie is available unless `T` is trivially -// destructible and the call to `operator delete[]` is not a sized operator delete. Under ABIs other -// than the Itanium ABI, we assume there are no array cookies. +// Under the Itanium C++ ABI [1] and the ARM ABI which derives from it, we know that an array cookie is available +// unless `T` is trivially destructible and the call to `operator delete[]` is not a sized operator delete. Under +// other ABIs, we assume there are no array cookies. // // [1]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#array-cookies -#ifdef _LIBCPP_ABI_ITANIUM +#if defined(_LIBCPP_ABI_ITANIUM) || defined(_LIBCPP_ABI_ITANIUM_WITH_ARM_DIFFERENCES) // TODO: Use a builtin instead -// TODO: We should factor in the choice of the usual deallocation function in this determination. +// TODO: We should factor in the choice of the usual deallocation function in this determination: +// a cookie may be available in more cases but we ignore those for now. template struct __has_array_cookie : _Not > {}; #else @@ -41,13 +43,79 @@ template struct __has_array_cookie : false_type {}; #endif +struct __itanium_array_cookie { + size_t __element_count; +}; + +template +struct [[__gnu__::__aligned__(_LIBCPP_ALIGNOF(_Tp))]] __arm_array_cookie { + size_t __element_size; + size_t __element_count; +}; + +// Return the element count in the array cookie located before the given pointer. +// +// In the Itanium ABI [1] +// ---------------------- +// The element count is stored immediately before the first element of the array. If the preferred alignment +// of array elements (which is different from the ABI alignment) is more than that of size_t, additional +// padding bytes exist before the array cookie. Assuming array elements of size and alignment 16 bytes, that +// gives us the following layout: +// +// |ooooooooxxxxxxxxaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddd| +// ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// | ^^^^^^^^ | +// | | array elements +// padding | +// element count +// +// +// In the Itanium ABI with ARM differences [2] +// ------------------------------------------- +// The array cookie is stored at the very start of the allocation and it has the following form: +// +// struct array_cookie { +// std::size_t element_size; // element_size != 0 +// std::size_t element_count; +// }; +// +// Assuming elements of size and alignment 32 bytes, this gives us the following layout: +// +// |xxxxxxxxXXXXXXXXooooooooooooooooaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb| +// ^^^^^^^^ ^^^^^^^^^^^^^^^^ +// | ^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// element size | padding | +// element count array elements +// +// We must be careful to take into account the alignment of the array cookie, which may result in padding +// bytes between the element count and the first element of the array. Note that for ARM, the compiler +// aligns the array cookie using the ABI alignment, not the preferred alignment of array elements. +// +// [1]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#array-cookies +// [2]: https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-C++-differences template // Avoid failures when -fsanitize-address-poison-custom-array-cookie is enabled -_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") size_t __get_array_cookie(_Tp const* __ptr) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") size_t __get_array_cookie([[__maybe_unused__]] _Tp const* __ptr) { static_assert( __has_array_cookie<_Tp>::value, "Trying to access the array cookie of a type that is not guaranteed to have one"); - size_t const* __cookie = reinterpret_cast(__ptr) - 1; // TODO: Use a builtin instead - return *__cookie; + +#if defined(_LIBCPP_ABI_ITANIUM) + using _ArrayCookie = __itanium_array_cookie; +#elif defined(_LIBCPP_ABI_ITANIUM_WITH_ARM_DIFFERENCES) + using _ArrayCookie = __arm_array_cookie<_Tp>; +#else + static_assert(false, "The array cookie layout is unknown on this ABI"); + struct _ArrayCookie { // dummy definition required to make the function parse + size_t element_count; + }; +#endif + + char const* __array_cookie_start = reinterpret_cast(__ptr) - sizeof(_ArrayCookie); + _ArrayCookie __cookie; + // This is necessary to avoid violating strict aliasing. It's valid because _ArrayCookie is an + // implicit lifetime type. + __builtin_memcpy(std::addressof(__cookie), __array_cookie_start, sizeof(_ArrayCookie)); + return __cookie.__element_count; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h index fb7b7b7afcc8c..29e503931b0be 100644 --- a/libcxx/include/__memory/compressed_pair.h +++ b/libcxx/include/__memory/compressed_pair.h @@ -80,21 +80,45 @@ class __compressed_pair_padding { template class __compressed_pair_padding<_ToPad, true> {}; -# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ - _LIBCPP_NO_UNIQUE_ADDRESS __attribute__((__aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ - _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ - _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ - _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _) - -# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \ - _LIBCPP_NO_UNIQUE_ADDRESS \ - __attribute__((__aligned__(::std::__compressed_pair_alignment), \ - __aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ - _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ - _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ - _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \ - _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \ - _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding3_, __LINE__, _) +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef _LIBCPP_COMPILER_GCC +# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ + _LIBCPP_NO_UNIQUE_ADDRESS __attribute__((__aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _) + +# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \ + _LIBCPP_NO_UNIQUE_ADDRESS \ + __attribute__((__aligned__(::std::__compressed_pair_alignment), \ + __aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding3_, __LINE__, _) +# else +# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ + struct { \ + _LIBCPP_NO_UNIQUE_ADDRESS \ + __attribute__((__aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \ + } + +# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \ + struct { \ + _LIBCPP_NO_UNIQUE_ADDRESS \ + __attribute__((__aligned__(::std::__compressed_pair_alignment), \ + __aligned__(::std::__compressed_pair_alignment))) T1 Initializer1; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \ + _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \ + _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding _LIBCPP_CONCAT3(__padding3_, __LINE__, _); \ + } +# endif #else # define _LIBCPP_COMPRESSED_PAIR(T1, Name1, T2, Name2) \ diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index 327b349f476a7..364f056d8d2cf 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -410,8 +410,13 @@ struct __segmented_iterator_traits<_JoinViewIterator> { static constexpr _LIBCPP_HIDE_FROM_ABI _JoinViewIterator __compose(__segment_iterator __seg_iter, __local_iterator __local_iter) { - return _JoinViewIterator( - std::move(__seg_iter).__get_data(), std::move(__seg_iter).__get_iter(), std::move(__local_iter)); + auto&& __parent = std::move(__seg_iter).__get_data(); + auto&& __outer = std::move(__seg_iter).__get_iter(); + if (__local_iter == ranges::end(*__outer)) { + ++__outer; + return _JoinViewIterator(*__parent, __outer); + } + return _JoinViewIterator(__parent, __outer, std::move(__local_iter)); } }; diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h index 5ff2efbe5faaf..3f5626c014432 100644 --- a/libcxx/include/__type_traits/invoke.h +++ b/libcxx/include/__type_traits/invoke.h @@ -67,20 +67,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__builtin_invoke) -template -using __invoke_result_t _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...)); - template struct __invoke_result_impl {}; template -struct __invoke_result_impl<__void_t<__invoke_result_t<_Args...> >, _Args...> { - using type _LIBCPP_NODEBUG = __invoke_result_t<_Args...>; +struct __invoke_result_impl<__void_t()...))>, _Args...> { + using type _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...)); }; template using __invoke_result _LIBCPP_NODEBUG = __invoke_result_impl; +template +using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Args...>::type; + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __invoke_result_t<_Args...> __invoke(_Args&&... __args) _NOEXCEPT_(noexcept(__builtin_invoke(std::forward<_Args>(__args)...))) { diff --git a/libcxx/include/__type_traits/is_unqualified.h b/libcxx/include/__type_traits/is_unqualified.h new file mode 100644 index 0000000000000..7970b3611601f --- /dev/null +++ b/libcxx/include/__type_traits/is_unqualified.h @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___TYPE_TRAITS_IS_UNQUALIFIED_H +#define _LIBCPP___TYPE_TRAITS_IS_UNQUALIFIED_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +inline const bool __is_unqualified_v = __is_same(_Tp, __remove_cvref(_Tp)); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_UNQUALIFIED_H diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map index d6b92204f4376..46815eaffa8bd 100644 --- a/libcxx/include/ext/hash_map +++ b/libcxx/include/ext/hash_map @@ -744,7 +744,7 @@ public: _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); } _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__emplace_unique(__x); } + _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__emplace_multi(__x); } _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x); } template _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last); @@ -831,7 +831,7 @@ template template inline void hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) - __table_.__emplace_unique(*__first); + __table_.__emplace_multi(*__first); } template diff --git a/libcxx/include/ext/hash_set b/libcxx/include/ext/hash_set index 7fd5df24ed3a8..62a7a0dbcffb9 100644 --- a/libcxx/include/ext/hash_set +++ b/libcxx/include/ext/hash_set @@ -458,7 +458,7 @@ public: _LIBCPP_HIDE_FROM_ABI const_iterator begin() const { return __table_.begin(); } _LIBCPP_HIDE_FROM_ABI const_iterator end() const { return __table_.end(); } - _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__emplace_unique(__x); } + _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return __table_.__emplace_multi(__x); } _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x); } template _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last); @@ -543,7 +543,7 @@ template template inline void hash_multiset<_Value, _Hash, _Pred, _Alloc>::insert(_InputIterator __first, _InputIterator __last) { for (; __first != __last; ++__first) - __table_.__emplace_unique(*__first); + __table_.__emplace_multi(*__first); } template diff --git a/libcxx/include/fstream b/libcxx/include/fstream index c86f709bedb80..6d3f20fff688f 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -401,6 +401,14 @@ private: } } } + + _LIBCPP_HIDE_FROM_ABI typename traits_type::int_type __overflow_failed() { + if (this->pptr() == this->epptr() + 1) { + this->pbump(-1); // lose the character we overflowed above -- we don't really have a + // choice since we couldn't commit the contents of the put area + } + return traits_type::eof(); + } }; template @@ -841,8 +849,9 @@ typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits> if (__always_noconv_) { size_t __n = static_cast(this->pptr() - this->pbase()); - if (std::fwrite(this->pbase(), sizeof(char_type), __n, __file_) != __n) - return traits_type::eof(); + if (std::fwrite(this->pbase(), sizeof(char_type), __n, __file_) != __n) { + return __overflow_failed(); + } } else { if (!__cv_) std::__throw_bad_cast(); @@ -854,34 +863,38 @@ typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits> char* __extbuf_end = __extbuf_; do { codecvt_base::result __r = __cv_->out(__st_, __b, __p, __end, __extbuf_, __extbuf_ + __ebs_, __extbuf_end); - if (__end == __b) - return traits_type::eof(); + if (__end == __b) { + return __overflow_failed(); + } // No conversion needed: output characters directly to the file, done. if (__r == codecvt_base::noconv) { size_t __n = static_cast(__p - __b); - if (std::fwrite(__b, 1, __n, __file_) != __n) - return traits_type::eof(); + if (std::fwrite(__b, 1, __n, __file_) != __n) { + return __overflow_failed(); + } break; // Conversion successful: output the converted characters to the file, done. } else if (__r == codecvt_base::ok) { size_t __n = static_cast(__extbuf_end - __extbuf_); - if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) - return traits_type::eof(); + if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) { + return __overflow_failed(); + } break; // Conversion partially successful: output converted characters to the file and repeat with the // remaining characters. } else if (__r == codecvt_base::partial) { size_t __n = static_cast(__extbuf_end - __extbuf_); - if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) - return traits_type::eof(); + if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) { + return __overflow_failed(); + } __b = const_cast(__end); continue; } else { - return traits_type::eof(); + return __overflow_failed(); } } while (true); } diff --git a/libcxx/include/map b/libcxx/include/map index 2251565801470..3d88b32dd426b 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -692,12 +692,12 @@ public: # if _LIBCPP_STD_VER >= 14 template _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const { - return __comp_(__x, __y.__get_value().first); + return __comp_(__x, __y.first); } template _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const { - return __comp_(__x.__get_value().first, __y); + return __comp_(__x.first, __y); } # endif }; diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 61ba1c381b2b3..4509dc20c6e65 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -336,6 +336,7 @@ module std_core [system] { header "__type_traits/is_union.h" export std_core.type_traits.integral_constant } + module is_unqualified { header "__type_traits/is_unqualified.h" } module is_unsigned { header "__type_traits/is_unsigned.h" export std_core.type_traits.integral_constant @@ -2353,6 +2354,9 @@ module std [system] { header "__std_mbstate_t.h" export * } + module log_hardening_failure { + header "__log_hardening_failure" + } module verbose_abort { header "__verbose_abort" } diff --git a/libcxx/include/string b/libcxx/include/string index 514dd91c7c172..d282071abf11f 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -974,7 +974,12 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() _NOEXCEPT_(is_nothrow_default_constructible::value) - : __rep_() { +# if _LIBCPP_STD_VER >= 20 // TODO(LLVM 23): Remove this condition; this is a workaround for https://llvm.org/PR154567 + : __rep_(__short()) +# else + : __rep_() +# endif + { __annotate_new(0); } @@ -984,7 +989,12 @@ public: # else _NOEXCEPT # endif - : __rep_(), __alloc_(__a) { +# if _LIBCPP_STD_VER >= 20 // TODO(LLVM 23): Remove this condition; this is a workaround for https://llvm.org/PR154567 + : __rep_(__short()), +# else + : __rep_(), +# endif + __alloc_(__a) { __annotate_new(0); } diff --git a/libcxx/lib/abi/CMakeLists.txt b/libcxx/lib/abi/CMakeLists.txt index 7c08bd06c50b2..8f277aad2dcd5 100644 --- a/libcxx/lib/abi/CMakeLists.txt +++ b/libcxx/lib/abi/CMakeLists.txt @@ -16,6 +16,9 @@ function(cxx_abi_list_identifier result triple abi_library abi_version unstable elseif("${triple}" MATCHES "freebsd") # Ignore the major and minor versions of freebsd targets. string(REGEX REPLACE "freebsd[0-9]+\\.[0-9]+" "freebsd" triple "${triple}") + elseif("${triple}" MATCHES "aix") + # Ignore the V.R.M.F version string of aix targets. + string(REGEX REPLACE "aix[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" "aix" triple "${triple}") endif() list(APPEND abi_properties "${triple}") list(APPEND abi_properties "${abi_library}") diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 97fe57a5f24f8..f59fe0e08fccb 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -309,6 +309,7 @@ add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS}) # Build the experimental static library set(LIBCXX_EXPERIMENTAL_SOURCES experimental/keep.cpp + experimental/log_hardening_failure.cpp ) if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch") diff --git a/libcxx/src/algorithm.cpp b/libcxx/src/algorithm.cpp index d388fee5f99cc..8157be6f7406e 100644 --- a/libcxx/src/algorithm.cpp +++ b/libcxx/src/algorithm.cpp @@ -13,6 +13,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template void __sort(RandomAccessIterator first, RandomAccessIterator last, Comp comp) { + if (first == last) // log(0) is undefined, so don't try computing the depth + return; + auto depth_limit = 2 * std::__bit_log2(static_cast(last - first)); // Only use bitset partitioning for arithmetic types. We should also check diff --git a/libcxx/src/experimental/log_hardening_failure.cpp b/libcxx/src/experimental/log_hardening_failure.cpp new file mode 100644 index 0000000000000..f836c15452249 --- /dev/null +++ b/libcxx/src/experimental/log_hardening_failure.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 <__config> +#include <__log_hardening_failure> +#include + +#ifdef __BIONIC__ +# include +#endif // __BIONIC__ + +_LIBCPP_BEGIN_NAMESPACE_STD + +void __log_hardening_failure(const char* message) noexcept { + // Always log the message to `stderr` in case the platform-specific system calls fail. + std::fputs(message, stderr); + +#if defined(__BIONIC__) + // Show error in logcat. The latter two arguments are ignored on Android. + openlog("libc++", 0, 0); + syslog(LOG_CRIT, "%s", message); + closelog(); +#endif +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/extensions/gnu/hash_multimap/insert.pass.cpp b/libcxx/test/extensions/gnu/hash_multimap/insert.pass.cpp new file mode 100644 index 0000000000000..ea80359f1fea2 --- /dev/null +++ b/libcxx/test/extensions/gnu/hash_multimap/insert.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated + +// hash_multimap::insert + +#include +#include + +int main(int, char**) { + __gnu_cxx::hash_multimap map; + + map.insert(std::make_pair(1, 1)); + map.insert(std::make_pair(1, 1)); + + assert(map.size() == 2); + assert(map.equal_range(1).first == map.begin()); + assert(map.equal_range(1).second == map.end()); + + std::pair arr[] = {std::make_pair(1, 1), std::make_pair(1, 1)}; + + map.insert(arr, arr + 2); + + assert(map.size() == 4); + assert(map.equal_range(1).first == map.begin()); + assert(map.equal_range(1).second == map.end()); + + return 0; +} diff --git a/libcxx/test/extensions/gnu/hash_multiset/insert.pass.cpp b/libcxx/test/extensions/gnu/hash_multiset/insert.pass.cpp new file mode 100644 index 0000000000000..1a60cac158a40 --- /dev/null +++ b/libcxx/test/extensions/gnu/hash_multiset/insert.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated + +// hash_multimap::insert + +#include +#include + +int main(int, char**) { + __gnu_cxx::hash_multiset map; + + map.insert(1); + map.insert(1); + + assert(map.size() == 2); + assert(map.equal_range(1).first == map.begin()); + assert(map.equal_range(1).second == map.end()); + + int arr[] = {1, 1}; + + map.insert(arr, arr + 2); + + assert(map.size() == 4); + assert(map.equal_range(1).first == map.begin()); + assert(map.equal_range(1).second == map.end()); + + return 0; +} diff --git a/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp new file mode 100644 index 0000000000000..dda071b8d0296 --- /dev/null +++ b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Basic smoke test for `__log_hardening_failure`. +// +// UNSUPPORTED: c++03 +// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic + +#include <__log_hardening_failure> + +#include "test_macros.h" + +ASSERT_NOEXCEPT(std::__log_hardening_failure("")); + +int main(int, char**) { + std::__log_hardening_failure("Some message"); + // It's difficult to properly test platform-specific logging behavior of the function; just make sure it exists and + // can be called at runtime. + + return 0; +} diff --git a/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp new file mode 100644 index 0000000000000..e0598b4ff1746 --- /dev/null +++ b/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp @@ -0,0 +1,168 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding + +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +template +class small_pointer { + std::uint16_t offset; +}; + +template +class small_iter_allocator { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::uint16_t; + using difference_type = std::int16_t; + + small_iter_allocator() TEST_NOEXCEPT {} + + template + small_iter_allocator(small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; } + friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } +}; + +template +class final_small_iter_allocator final { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::uint16_t; + using difference_type = std::int16_t; + + final_small_iter_allocator() TEST_NOEXCEPT {} + + template + final_small_iter_allocator(final_small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(final_small_iter_allocator, final_small_iter_allocator) { return true; } + friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; } +}; + +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +template +using map_alloc = std::map, Alloc>; + +struct user_struct { + map_alloc > > v; + [[no_unique_address]] common_base_allocator a; +}; + +#if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 32, ""); +# else +static_assert(sizeof(user_struct) == 24, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); + +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 40, ""); +static_assert(sizeof(map_alloc > >) == 6, ""); +static_assert(sizeof(map_alloc > >) == 8, ""); + +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 40, ""); +static_assert(sizeof(map_alloc > >) == 6, ""); +static_assert(sizeof(map_alloc > >) == 8, ""); + +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); + +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 8, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); + +struct TEST_ALIGNAS(32) AlignedLess {}; + +static_assert(sizeof(std::map) == 64, ""); +static_assert(TEST_ALIGNOF(std::map) == 32, ""); + +#elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 16, ""); +# else +static_assert(sizeof(user_struct) == 12, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); + +static_assert(sizeof(map_alloc > >) == 12, ""); +static_assert(sizeof(map_alloc > >) == 12, ""); +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 6, ""); +static_assert(sizeof(map_alloc > >) == 8, ""); + +static_assert(sizeof(map_alloc > >) == 12, ""); +static_assert(sizeof(map_alloc > >) == 12, ""); +static_assert(sizeof(map_alloc > >) == 24, ""); +static_assert(sizeof(map_alloc > >) == 6, ""); +static_assert(sizeof(map_alloc > >) == 8, ""); + +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); + +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 4, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); +static_assert(TEST_ALIGNOF(map_alloc > >) == 2, ""); + +struct TEST_ALIGNAS(32) AlignedLess {}; + +static_assert(sizeof(std::map) == 64); +static_assert(TEST_ALIGNOF(std::map) == 32); + +#else +# error std::size_t has an unexpected size +#endif diff --git a/libcxx/test/libcxx/containers/associative/set/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/set/abi.compile.pass.cpp new file mode 100644 index 0000000000000..14f89b6c9deae --- /dev/null +++ b/libcxx/test/libcxx/containers/associative/set/abi.compile.pass.cpp @@ -0,0 +1,168 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding + +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +template +class small_pointer { + std::uint16_t offset; +}; + +template +class small_iter_allocator { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::uint16_t; + using difference_type = std::int16_t; + + small_iter_allocator() TEST_NOEXCEPT {} + + template + small_iter_allocator(small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; } + friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } +}; + +template +class final_small_iter_allocator final { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::uint16_t; + using difference_type = std::int16_t; + + final_small_iter_allocator() TEST_NOEXCEPT {} + + template + final_small_iter_allocator(final_small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(final_small_iter_allocator, final_small_iter_allocator) { return true; } + friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; } +}; + +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +template +using set_alloc = std::set, Alloc>; + +struct user_struct { + set_alloc > v; + [[no_unique_address]] common_base_allocator a; +}; + +#if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 32, ""); +# else +static_assert(sizeof(user_struct) == 24, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); + +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 40, ""); +static_assert(sizeof(set_alloc >) == 6, ""); +static_assert(sizeof(set_alloc >) == 8, ""); + +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 40, ""); +static_assert(sizeof(set_alloc >) == 6, ""); +static_assert(sizeof(set_alloc >) == 8, ""); + +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); + +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); + +struct TEST_ALIGNAS(32) AlignedLess {}; + +static_assert(sizeof(std::set) == 64, ""); +static_assert(TEST_ALIGNOF(std::set) == 32, ""); + +#elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 16, ""); +# else +static_assert(sizeof(user_struct) == 12, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); + +static_assert(sizeof(set_alloc >) == 12, ""); +static_assert(sizeof(set_alloc >) == 12, ""); +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 6, ""); +static_assert(sizeof(set_alloc >) == 8, ""); + +static_assert(sizeof(set_alloc >) == 12, ""); +static_assert(sizeof(set_alloc >) == 12, ""); +static_assert(sizeof(set_alloc >) == 24, ""); +static_assert(sizeof(set_alloc >) == 6, ""); +static_assert(sizeof(set_alloc >) == 8, ""); + +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); + +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); +static_assert(TEST_ALIGNOF(set_alloc >) == 2, ""); + +struct TEST_ALIGNAS(32) AlignedLess {}; + +static_assert(sizeof(std::set) == 64); +static_assert(TEST_ALIGNOF(std::set) == 32); + +#else +# error std::size_t has an unexpected size +#endif diff --git a/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp index 55d42a8d017e1..60c3e5bf31b00 100644 --- a/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp @@ -12,8 +12,6 @@ // unordered containers changes when bounded unique_ptr is enabled. // UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr -// XFAIL: FROZEN-CXX03-HEADERS-FIXME - #include #include @@ -66,10 +64,41 @@ class final_small_iter_allocator final { friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + template using unordered_map_alloc = std::unordered_map, std::equal_to, Alloc>; +struct user_struct { + unordered_map_alloc > > v; + [[no_unique_address]] common_base_allocator a; +}; + #if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 48, ""); +# else +static_assert(sizeof(user_struct) == 40, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); static_assert(sizeof(unordered_map_alloc > >) == 40, ""); static_assert(sizeof(unordered_map_alloc > >) == 40, ""); @@ -98,12 +127,22 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc) == 64, ""); +# else +static_assert(sizeof(std::unordered_map) == 96, ""); +# endif static_assert(TEST_ALIGNOF(std::unordered_map) == 32, ""); #elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 24, ""); +# else +static_assert(sizeof(user_struct) == 20, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); static_assert(sizeof(unordered_map_alloc > >) == 20, ""); static_assert(sizeof(unordered_map_alloc > >) == 20, ""); @@ -133,7 +172,12 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc) == 64); +# else +static_assert(sizeof(std::unordered_map) == 96); +# endif static_assert(TEST_ALIGNOF(std::unordered_map) == 32); #else diff --git a/libcxx/test/libcxx/containers/associative/unord.set/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/unord.set/abi.compile.pass.cpp index bee2012bbea29..0216cb1213edf 100644 --- a/libcxx/test/libcxx/containers/associative/unord.set/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/associative/unord.set/abi.compile.pass.cpp @@ -12,8 +12,6 @@ // unordered containers changes when bounded unique_ptr is enabled. // UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr -// XFAIL: FROZEN-CXX03-HEADERS-FIXME - #include #include @@ -66,10 +64,41 @@ class final_small_iter_allocator final { friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + template using unordered_set_alloc = std::unordered_set, std::equal_to, Alloc>; +struct user_struct { + unordered_set_alloc > v; + [[no_unique_address]] common_base_allocator a; +}; + #if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 48, ""); +# else +static_assert(sizeof(user_struct) == 40, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); static_assert(sizeof(unordered_set_alloc >) == 40, ""); static_assert(sizeof(unordered_set_alloc >) == 40, ""); @@ -98,11 +127,22 @@ static_assert(TEST_ALIGNOF(unordered_set_alloc) == 64, ""); +# else +static_assert(sizeof(std::unordered_set) == 96, ""); +# endif static_assert(TEST_ALIGNOF(std::unordered_set) == 32, ""); #elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 24, ""); +# else +static_assert(sizeof(user_struct) == 20, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); static_assert(sizeof(unordered_set_alloc >) == 20, ""); static_assert(sizeof(unordered_set_alloc >) == 20, ""); @@ -131,7 +171,12 @@ static_assert(TEST_ALIGNOF(unordered_set_alloc) == 64); +# else +static_assert(sizeof(std::unordered_set) == 96); +# endif static_assert(TEST_ALIGNOF(std::unordered_set) == 32); #else diff --git a/libcxx/test/libcxx/containers/sequences/deque/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/deque/abi.compile.pass.cpp index 30586d8b2422c..7eaf64ea09d13 100644 --- a/libcxx/test/libcxx/containers/sequences/deque/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/sequences/deque/abi.compile.pass.cpp @@ -60,6 +60,25 @@ class final_small_iter_allocator final { friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + #if __SIZE_WIDTH__ == 64 static_assert(sizeof(std::deque) == 48, ""); @@ -67,24 +86,38 @@ static_assert(sizeof(std::deque >) == 48, ""); static_assert(sizeof(std::deque >) == 80, ""); static_assert(sizeof(std::deque >) == 12, ""); static_assert(sizeof(std::deque >) == 16, ""); +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(std::deque >) == 56, ""); +# else +static_assert(sizeof(std::deque >) == 48, ""); +# endif static_assert(sizeof(std::deque) == 48, ""); static_assert(sizeof(std::deque >) == 48, ""); static_assert(sizeof(std::deque >) == 80, ""); static_assert(sizeof(std::deque >) == 12, ""); static_assert(sizeof(std::deque >) == 16, ""); +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(std::deque >) == 56, ""); +# else +static_assert(sizeof(std::deque >) == 48, ""); +# endif static_assert(TEST_ALIGNOF(std::deque) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); +static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); static_assert(TEST_ALIGNOF(std::deque) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); +static_assert(TEST_ALIGNOF(std::deque >) == 8, ""); #elif __SIZE_WIDTH__ == 32 @@ -93,24 +126,38 @@ static_assert(sizeof(std::deque >) == 24, ""); static_assert(sizeof(std::deque >) == 48, ""); static_assert(sizeof(std::deque >) == 12, ""); static_assert(sizeof(std::deque >) == 16, ""); +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(std::deque >) == 28, ""); +# else +static_assert(sizeof(std::deque >) == 24, ""); +# endif static_assert(sizeof(std::deque) == 24, ""); static_assert(sizeof(std::deque >) == 24, ""); static_assert(sizeof(std::deque >) == 48, ""); static_assert(sizeof(std::deque >) == 12, ""); static_assert(sizeof(std::deque >) == 16, ""); +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(std::deque >) == 28, ""); +# else +static_assert(sizeof(std::deque >) == 24, ""); +# endif static_assert(TEST_ALIGNOF(std::deque) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); +static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); static_assert(TEST_ALIGNOF(std::deque) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); static_assert(TEST_ALIGNOF(std::deque >) == 2, ""); +static_assert(TEST_ALIGNOF(std::deque >) == 4, ""); #else # error std::size_t has an unexpected size diff --git a/libcxx/test/libcxx/containers/sequences/forwardlist/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/forwardlist/abi.compile.pass.cpp new file mode 100644 index 0000000000000..cb500f9c4d61b --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/forwardlist/abi.compile.pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +template +class small_pointer { + std::uint16_t offset; +}; + +template +class small_iter_allocator { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::int16_t; + using difference_type = std::int16_t; + + small_iter_allocator() TEST_NOEXCEPT {} + + template + small_iter_allocator(small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; } + friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } +}; + +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +struct user_struct { + std::forward_list > v; + [[no_unique_address]] common_base_allocator a; +}; + +#if __SIZE_WIDTH__ == 64 +static_assert(sizeof(user_struct) == 16, ""); +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); + +static_assert(sizeof(std::forward_list) == 8, ""); +static_assert(sizeof(std::forward_list >) == 8, ""); +static_assert(sizeof(std::forward_list >) == 24, ""); +static_assert(sizeof(std::forward_list >) == 2, ""); + +static_assert(sizeof(std::forward_list) == 8, ""); +static_assert(sizeof(std::forward_list >) == 8, ""); +static_assert(sizeof(std::forward_list >) == 24, ""); +static_assert(sizeof(std::forward_list >) == 2, ""); + +static_assert(TEST_ALIGNOF(std::forward_list) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 2, ""); + +static_assert(TEST_ALIGNOF(std::forward_list) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 8, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 2, ""); + +#elif __SIZE_WIDTH__ == 32 +static_assert(sizeof(user_struct) == 8, ""); +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); + +static_assert(sizeof(std::forward_list) == 4, ""); +static_assert(sizeof(std::forward_list >) == 4, ""); +static_assert(sizeof(std::forward_list >) == 16, ""); +static_assert(sizeof(std::forward_list >) == 2, ""); + +static_assert(sizeof(std::forward_list) == 4, ""); +static_assert(sizeof(std::forward_list >) == 4, ""); +static_assert(sizeof(std::forward_list >) == 16, ""); +static_assert(sizeof(std::forward_list >) == 2, ""); + +static_assert(TEST_ALIGNOF(std::forward_list) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 2, ""); + +static_assert(TEST_ALIGNOF(std::forward_list) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 4, ""); +static_assert(TEST_ALIGNOF(std::forward_list >) == 2, ""); + +#else +# error std::size_t has an unexpected size +#endif diff --git a/libcxx/test/libcxx/containers/sequences/list/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/list/abi.compile.pass.cpp index a16ae1d527921..4b9c295c46f2c 100644 --- a/libcxx/test/libcxx/containers/sequences/list/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/sequences/list/abi.compile.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding + #include #include @@ -38,7 +40,38 @@ class small_iter_allocator { friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +struct user_struct { + std::list > v; + [[no_unique_address]] common_base_allocator a; +}; + #if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 32, ""); +# else +static_assert(sizeof(user_struct) == 24, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); static_assert(sizeof(std::list) == 24, ""); static_assert(sizeof(std::list >) == 24, ""); @@ -61,6 +94,13 @@ static_assert(TEST_ALIGNOF(std::list >) == 8, ""); static_assert(TEST_ALIGNOF(std::list >) == 2, ""); #elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 16, ""); +# else +static_assert(sizeof(user_struct) == 12, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); static_assert(sizeof(std::list) == 12, ""); static_assert(sizeof(std::list >) == 12, ""); diff --git a/libcxx/test/libcxx/containers/sequences/vector.bool/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector.bool/abi.compile.pass.cpp index cc6b0d94e7daf..598d54ffb91a0 100644 --- a/libcxx/test/libcxx/containers/sequences/vector.bool/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/sequences/vector.bool/abi.compile.pass.cpp @@ -40,7 +40,37 @@ class small_iter_allocator { friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +struct user_struct { + std::vector > v; + [[no_unique_address]] common_base_allocator a; +}; + #if __SIZE_WIDTH__ == 64 +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 32, ""); +# else +static_assert(sizeof(user_struct) == 24, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); static_assert(sizeof(std::vector) == 24, ""); static_assert(sizeof(std::vector >) == 24, ""); @@ -53,6 +83,13 @@ static_assert(TEST_ALIGNOF(std::vector >) == 8, ""); static_assert(TEST_ALIGNOF(std::vector >) == 2, ""); #elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 16, ""); +# else +static_assert(sizeof(user_struct) == 12, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); static_assert(sizeof(std::vector) == 12, ""); static_assert(sizeof(std::vector >) == 12, ""); diff --git a/libcxx/test/libcxx/containers/sequences/vector/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/abi.compile.pass.cpp index 57684951c8e8e..6dc0504991b39 100644 --- a/libcxx/test/libcxx/containers/sequences/vector/abi.compile.pass.cpp +++ b/libcxx/test/libcxx/containers/sequences/vector/abi.compile.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding + #include #include @@ -46,7 +48,38 @@ class small_iter_allocator { friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } }; +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +struct user_struct { + std::vector > v; + [[no_unique_address]] common_base_allocator a; +}; + #if __SIZE_WIDTH__ == 64 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 32, ""); +# else +static_assert(sizeof(user_struct) == 24, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); static_assert(sizeof(std::vector) == 24, ""); static_assert(sizeof(std::vector >) == 24, ""); @@ -69,6 +102,13 @@ static_assert(TEST_ALIGNOF(std::vector >) == 8, ""); static_assert(TEST_ALIGNOF(std::vector >) == 2, ""); #elif __SIZE_WIDTH__ == 32 +// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed +# ifdef TEST_COMPILER_GCC +static_assert(sizeof(user_struct) == 16, ""); +# else +static_assert(sizeof(user_struct) == 12, ""); +# endif +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); static_assert(sizeof(std::vector) == 12, ""); static_assert(sizeof(std::vector >) == 12, ""); diff --git a/libcxx/test/libcxx/containers/strings/basic.string/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/strings/basic.string/abi.compile.pass.cpp new file mode 100644 index 0000000000000..cf802e214d07c --- /dev/null +++ b/libcxx/test/libcxx/containers/strings/basic.string/abi.compile.pass.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +template +class small_pointer { +public: + using value_type = T; + using difference_type = std::int16_t; + using pointer = small_pointer; + using reference = T&; + using iterator_category = std::random_access_iterator_tag; + +private: + std::uint16_t offset; +}; + +template +class small_iter_allocator { +public: + using value_type = T; + using pointer = small_pointer; + using size_type = std::int16_t; + using difference_type = std::int16_t; + + small_iter_allocator() TEST_NOEXCEPT {} + + template + small_iter_allocator(small_iter_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; } + friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; } +}; + +struct allocator_base {}; + +// Make sure that types with a common base type don't get broken. See https://llvm.org/PR154146 +template +struct common_base_allocator : allocator_base { + using value_type = T; + + common_base_allocator() TEST_NOEXCEPT {} + + template + common_base_allocator(common_base_allocator) TEST_NOEXCEPT {} + + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t); + + friend bool operator==(common_base_allocator, common_base_allocator) { return true; } + friend bool operator!=(common_base_allocator, common_base_allocator) { return false; } +}; + +template +using string_alloc = std::basic_string, Alloc>; + +struct user_struct { + string_alloc > v; + [[no_unique_address]] common_base_allocator a; +}; + +#if __SIZE_WIDTH__ == 64 +static_assert(sizeof(user_struct) == 32, ""); +static_assert(TEST_ALIGNOF(user_struct) == 8, ""); + +static_assert(sizeof(string_alloc >) == 24, ""); +static_assert(sizeof(string_alloc >) == 24, ""); +static_assert(sizeof(string_alloc >) == 32, ""); +static_assert(sizeof(string_alloc >) == 6, ""); + +static_assert(TEST_ALIGNOF(string_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 8, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 2, ""); + +#elif __SIZE_WIDTH__ == 32 +static_assert(sizeof(user_struct) == 16, ""); +static_assert(TEST_ALIGNOF(user_struct) == 4, ""); + +static_assert(sizeof(string_alloc >) == 12, ""); +static_assert(sizeof(string_alloc >) == 12, ""); +static_assert(sizeof(string_alloc >) == 24, ""); +static_assert(sizeof(string_alloc >) == 6, ""); + +static_assert(TEST_ALIGNOF(string_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 4, ""); +static_assert(TEST_ALIGNOF(string_alloc >) == 2, ""); + +#else +# error std::size_t has an unexpected size +#endif diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp index 3cf497da233fb..3d97446ffe826 100644 --- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp +++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp @@ -29,3 +29,7 @@ #if !_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM # error "-fexperimental-library should enable the syncstream header" #endif + +#if !_LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC +# error "-fexperimental-library should allow using the Hardening observe semantic" +#endif diff --git a/libcxx/test/libcxx/thread/thread.barrier/assert.arrive.pass.cpp b/libcxx/test/libcxx/thread/thread.barrier/assert.arrive.pass.cpp index 419a603a037f8..2bc4648878f8e 100644 --- a/libcxx/test/libcxx/thread/thread.barrier/assert.arrive.pass.cpp +++ b/libcxx/test/libcxx/thread/thread.barrier/assert.arrive.pass.cpp @@ -8,6 +8,8 @@ // UNSUPPORTED: no-threads // UNSUPPORTED: c++03, c++11, c++14, c++17 // REQUIRES: libcpp-hardening-mode={{extensive|debug}} +// Without the assertion, the test will most likely time out. +// UNSUPPORTED: libcpp-assertion-semantic={{ignore|observe}} // XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing diff --git a/libcxx/test/libcxx/thread/thread.latch/assert.arrive_and_wait.pass.cpp b/libcxx/test/libcxx/thread/thread.latch/assert.arrive_and_wait.pass.cpp index e61679554a62e..30d36b5f6d7b5 100644 --- a/libcxx/test/libcxx/thread/thread.latch/assert.arrive_and_wait.pass.cpp +++ b/libcxx/test/libcxx/thread/thread.latch/assert.arrive_and_wait.pass.cpp @@ -18,6 +18,8 @@ // REQUIRES: has-unix-headers // REQUIRES: libcpp-hardening-mode={{extensive|debug}} +// Without the assertion, the test will most likely time out. +// UNSUPPORTED: libcpp-assertion-semantic={{ignore|observe}} // XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing #include diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/value.observers.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/value.observers.verify.cpp index 91a7db1d9a7c6..1a2d080d10c3c 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.expected/value.observers.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.expected/value.observers.verify.cpp @@ -124,8 +124,9 @@ void test() { #if _LIBCPP_HAS_EXCEPTIONS // expected-error-re@*:* {{call to deleted constructor of{{.*}}}} // expected-error-re@*:* {{call to deleted constructor of{{.*}}}} - // expected-error-re@*:* 1-2{{call to deleted constructor of{{.*}}}} - // expected-error-re@*:* 0-2{{call to deleted constructor of{{.*}}}} #endif +// These diagnostics can also additionally be produced by static_assert (see GH150601). +// expected-error-re@*:* 0-2{{call to deleted constructor of{{.*}}}} +// expected-error-re@*:* 0-2{{call to deleted constructor of{{.*}}}} } // clang-format on diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp index d7e6be9928a2d..5f730f0f5bba8 100644 --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp @@ -272,57 +272,100 @@ class Comparable { friend bool operator==(const Comparable& lhs, long long rhs) { return comparable_data[lhs.index_] == rhs; } }; -void test_deque() { - { // empty deque - std::deque data; - assert(std::ranges::find(data, 4) == data.end()); - assert(std::ranges::find(data.begin(), data.end(), 4) == data.end()); - } - - { // single element - match - std::deque data = {4}; - assert(std::ranges::find(data, 4) == data.begin()); - assert(std::ranges::find(data.begin(), data.end(), 4) == data.begin()); - } - - { // single element - no match - std::deque data = {3}; - assert(std::ranges::find(data, 4) == data.end()); - assert(std::ranges::find(data.begin(), data.end(), 4) == data.end()); - } - - // many elements - for (auto size : {2, 3, 1023, 1024, 1025, 2047, 2048, 2049}) { - { // last element match +void test_segmented_iterator_types() { + // Test the optimized find algorithm for types that implement the segment iterator trait + // deque + { + { // empty deque std::deque data; - data.resize(size); - std::fill(data.begin(), data.end(), 3); - data[size - 1] = 4; - assert(std::ranges::find(data, 4) == data.end() - 1); - assert(std::ranges::find(data.begin(), data.end(), 4) == data.end() - 1); + assert(std::ranges::find(data, 4) == data.end()); + assert(std::ranges::find(data.begin(), data.end(), 4) == data.end()); } - { // second-last element match - std::deque data; - data.resize(size); - std::fill(data.begin(), data.end(), 3); - data[size - 2] = 4; - assert(std::ranges::find(data, 4) == data.end() - 2); - assert(std::ranges::find(data.begin(), data.end(), 4) == data.end() - 2); + { // single element - match + std::deque data = {4}; + assert(std::ranges::find(data, 4) == data.begin()); + assert(std::ranges::find(data.begin(), data.end(), 4) == data.begin()); } - { // no match - std::deque data; - data.resize(size); - std::fill(data.begin(), data.end(), 3); + { // single element - no match + std::deque data = {3}; assert(std::ranges::find(data, 4) == data.end()); assert(std::ranges::find(data.begin(), data.end(), 4) == data.end()); } + + // many elements + for (auto size : {2, 3, 1023, 1024, 1025, 2047, 2048, 2049}) { + { // last element match + std::deque data; + data.resize(size); + std::fill(data.begin(), data.end(), 3); + data[size - 1] = 4; + assert(std::ranges::find(data, 4) == data.end() - 1); + assert(std::ranges::find(data.begin(), data.end(), 4) == data.end() - 1); + } + + { // second-last element match + std::deque data; + data.resize(size); + std::fill(data.begin(), data.end(), 3); + data[size - 2] = 4; + assert(std::ranges::find(data, 4) == data.end() - 2); + assert(std::ranges::find(data.begin(), data.end(), 4) == data.end() - 2); + } + + { // no match + std::deque data; + data.resize(size); + std::fill(data.begin(), data.end(), 3); + assert(std::ranges::find(data, 4) == data.end()); + assert(std::ranges::find(data.begin(), data.end(), 4) == data.end()); + } + } + } + // join_view ranges adaptor + { + { // single element - match + int data[1][1] = {{4}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::begin(joined)); + } + { // single element - no match + // (reproducer for https://llvm.org/PR158279, where the iterator would never reach the end sentinel) + int data[1][1] = {{3}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::end(joined)); + } + { // several sub-arrays of size 1 - match + int data[3][1] = {{0}, {4}, {0}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::next(std::ranges::begin(joined))); + } + { // several sub-arrays of size 2 - match in second element of an array + int data[3][2] = {{0, 0}, {0, 4}, {0, 0}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::next(std::ranges::begin(joined), 3)); + } + { // vector of empty vectors + std::vector> data = {{}, {}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::end(joined)); + } + { // vector of variably sized vectors - match + std::vector> data = {{}, {}, {3, 4}, {}, {}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::next(std::ranges::begin(joined))); + } + { // vector of variably sized vectors - no match + std::vector> data = {{}, {}, {3, 5}, {}, {}}; + auto joined = std::views::join(data); + assert(std::ranges::find(joined, 4) == std::ranges::end(joined)); + } } } int main(int, char**) { - test_deque(); + test_segmented_iterator_types(); test(); static_assert(test()); diff --git a/libcxx/test/std/containers/associative/map/map.ops/count0.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/count0.pass.cpp index c7ba765178969..62491e2bc4438 100644 --- a/libcxx/test/std/containers/associative/map/map.ops/count0.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.ops/count0.pass.cpp @@ -33,6 +33,10 @@ int main(int, char**) { typedef std::map M; assert(M().count(C2Int{5}) == 0); } + { + using M = std::map; + assert(M().count(C2Int{5}) == 0); + } return 0; } diff --git a/libcxx/test/std/containers/associative/map/map.ops/equal_range0.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/equal_range0.pass.cpp index 75724bdb387ce..57ce9339f6323 100644 --- a/libcxx/test/std/containers/associative/map/map.ops/equal_range0.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.ops/equal_range0.pass.cpp @@ -40,6 +40,13 @@ int main(int, char**) { P result = example.equal_range(C2Int{5}); assert(result.first == result.second); } + { + using M = std::map; + using P = std::pair; + M example; + P result = example.equal_range(C2Int{5}); + assert(result.first == result.second); + } return 0; } diff --git a/libcxx/test/std/containers/associative/map/map.ops/find0.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/find0.pass.cpp index 9825d6c5879b1..3f09d5608772d 100644 --- a/libcxx/test/std/containers/associative/map/map.ops/find0.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.ops/find0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.find(C2Int{5}) == example.end()); } + { + using M = std::map; + M example; + assert(example.find(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/containers/associative/map/map.ops/lower_bound0.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/lower_bound0.pass.cpp index fe7fe381a86eb..308a2ed1e3af0 100644 --- a/libcxx/test/std/containers/associative/map/map.ops/lower_bound0.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.ops/lower_bound0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.lower_bound(C2Int{5}) == example.end()); } + { + using M = std::map; + M example; + assert(example.lower_bound(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/containers/associative/map/map.ops/upper_bound0.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/upper_bound0.pass.cpp index 525aa673ea74b..332b71a84e9fb 100644 --- a/libcxx/test/std/containers/associative/map/map.ops/upper_bound0.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.ops/upper_bound0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.upper_bound(C2Int{5}) == example.end()); } + { + using M = std::map; + M example; + assert(example.upper_bound(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.ops/count0.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.ops/count0.pass.cpp index 233d1a11e1d6c..36f0ac2647ba3 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.ops/count0.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.ops/count0.pass.cpp @@ -33,6 +33,10 @@ int main(int, char**) { typedef std::multimap M; assert(M().count(C2Int{5}) == 0); } + { + using M = std::multimap; + assert(M().count(C2Int{5}) == 0); + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.ops/equal_range0.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.ops/equal_range0.pass.cpp index 0bead6c7938db..a362c03e26385 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.ops/equal_range0.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.ops/equal_range0.pass.cpp @@ -40,6 +40,13 @@ int main(int, char**) { P result = example.equal_range(C2Int{5}); assert(result.first == result.second); } + { + using M = std::multimap; + using P = std::pair; + M example; + P result = example.equal_range(C2Int{5}); + assert(result.first == result.second); + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.ops/find0.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.ops/find0.pass.cpp index 701d4e314e7a8..ccb0900e76835 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.ops/find0.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.ops/find0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.find(C2Int{5}) == example.end()); } + { + using M = std::multimap; + M example; + assert(example.find(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.ops/lower_bound0.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.ops/lower_bound0.pass.cpp index 79f994847f131..4b4853062001f 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.ops/lower_bound0.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.ops/lower_bound0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.lower_bound(C2Int{5}) == example.end()); } + { + using M = std::multimap; + M example; + assert(example.lower_bound(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.ops/upper_bound0.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.ops/upper_bound0.pass.cpp index 62f52416b9156..f2ae94577b6c1 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.ops/upper_bound0.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.ops/upper_bound0.pass.cpp @@ -36,6 +36,11 @@ int main(int, char**) { M example; assert(example.upper_bound(C2Int{5}) == example.end()); } + { + using M = std::multimap; + M example; + assert(example.upper_bound(C2Int{5}) == example.end()); + } return 0; } diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/overflow.writefail.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/overflow.writefail.pass.cpp new file mode 100644 index 0000000000000..27e06982d749b --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/overflow.writefail.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-filesystem + +// setrlimit(RLIMIT_FSIZE) seems to only work as intended on Apple platforms +// REQUIRES: target={{.+}}-apple-{{.+}} + +// + +// Make sure that we properly handle the case where we try to write content to a file +// but we fail to do so because std::fwrite fails. + +#include +#include +#include +#include +#include + +#include "platform_support.h" +#include "test_macros.h" + +#if __has_include() +# include +void limit_file_size_to(std::size_t bytes) { + rlimit lim = {bytes, bytes}; + assert(setrlimit(RLIMIT_FSIZE, &lim) == 0); + + std::signal(SIGXFSZ, [](int) {}); // ignore SIGXFSZ to ensure std::fwrite fails +} +#else +# error No known way to limit the amount of filesystem space available +#endif + +template +void test() { + std::string temp = get_temp_file_name(); + std::basic_filebuf fbuf; + assert(fbuf.open(temp, std::ios::out | std::ios::trunc)); + + std::size_t const limit = 100000; + limit_file_size_to(limit); + + std::basic_string large_block(limit / 10, CharT(42)); + + std::streamsize ret; + std::size_t bytes_written = 0; + while ((ret = fbuf.sputn(large_block.data(), large_block.size())) != 0) { + bytes_written += ret; + + // In theory, it's possible for an implementation to allow writing arbitrarily more bytes than + // set by setrlimit, but in practice if we bust 100x our limit, something else is wrong with the + // test and we'd end up looping forever. + assert(bytes_written < 100 * limit); + } + + fbuf.close(); +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/unord.hash/enum.pass.cpp b/libcxx/test/std/utilities/function.objects/unord.hash/enum.pass.cpp index fd1fbe5f113ba..05a19329f909a 100644 --- a/libcxx/test/std/utilities/function.objects/unord.hash/enum.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/unord.hash/enum.pass.cpp @@ -21,6 +21,10 @@ #include "test_macros.h" +#if TEST_STD_VER >= 11 +# include "poisoned_hash_helper.h" +#endif + enum class Colors { red, orange, yellow, green, blue, indigo, violet }; enum class Cardinals { zero, one, two, three, five=5 }; enum class LongColors : short { red, orange, yellow, green, blue, indigo, violet }; @@ -33,6 +37,12 @@ template void test() { +#if TEST_STD_VER >= 11 + test_hash_disabled(); + test_hash_disabled(); + test_hash_disabled(); +#endif + typedef std::hash H; #if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/utilities/function.objects/unord.hash/floating.pass.cpp b/libcxx/test/std/utilities/function.objects/unord.hash/floating.pass.cpp index b8f85e193dc8f..f6c31d068b231 100644 --- a/libcxx/test/std/utilities/function.objects/unord.hash/floating.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/unord.hash/floating.pass.cpp @@ -27,10 +27,20 @@ #include "test_macros.h" +#if TEST_STD_VER >= 11 +# include "poisoned_hash_helper.h" +#endif + template void test() { +#if TEST_STD_VER >= 11 + test_hash_disabled(); + test_hash_disabled(); + test_hash_disabled(); +#endif + typedef std::hash H; #if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/utilities/function.objects/unord.hash/integral.pass.cpp b/libcxx/test/std/utilities/function.objects/unord.hash/integral.pass.cpp index 14af7093c1e36..c798b3aa77ea5 100644 --- a/libcxx/test/std/utilities/function.objects/unord.hash/integral.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/unord.hash/integral.pass.cpp @@ -26,10 +26,20 @@ #include "test_macros.h" +#if TEST_STD_VER >= 11 +# include "poisoned_hash_helper.h" +#endif + template void test() { +#if TEST_STD_VER >= 11 + test_hash_disabled(); + test_hash_disabled(); + test_hash_disabled(); +#endif + typedef std::hash H; #if TEST_STD_VER <= 17 static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_bounded_array.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_bounded_array.pass.cpp index 09086a4c046d6..8e57e8913dcbe 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_bounded_array.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_bounded_array.pass.cpp @@ -7,9 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// The Clang version that Android currently uses in the CI is too old. -// XFAIL: LIBCXX-ANDROID-FIXME - // type_traits // is_bounded_array diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/has_unique_object_representations.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/has_unique_object_representations.compile.pass.cpp index 9aac871f2633f..bd7da40daf2bc 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/has_unique_object_representations.compile.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/has_unique_object_representations.compile.pass.cpp @@ -8,9 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14 -// The Clang version that Android currently uses in the CI is too old. -// XFAIL: LIBCXX-ANDROID-FIXME - // type_traits // has_unique_object_representations diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp index 7f4c90922d6c3..e2abfd17d27c3 100644 --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/default.pass.cpp @@ -82,6 +82,10 @@ TEST_CONSTEXPR_CXX23 bool test_basic() { p.get_deleter().set_state(5); assert(p.get_deleter().state() == 5); } +// TODO: Remove this check once https://llvm.org/PR154567 is fixed +#if TEST_STD_VER >= 23 && defined(TEST_COMPILER_CLANG) + if (!TEST_IS_CONSTANT_EVALUATED) +#endif { std::unique_ptr > p; assert(p.get() == 0); diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp index 45017a03b95dd..f5e0541684d13 100644 --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/nullptr.pass.cpp @@ -47,6 +47,10 @@ TEST_CONSTEXPR_CXX23 void test_basic() { assert(p.get() == 0); assert(p.get_deleter().state() == 0); } +// TODO: Remove this check once https://llvm.org/PR154567 is fixed +#if TEST_STD_VER >= 23 && defined(TEST_COMPILER_CLANG) + if (!TEST_IS_CONSTANT_EVALUATED) +#endif { std::unique_ptr > p(nullptr); assert(p.get() == 0); diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp index cbce5c9c74c5a..e9912d4574af6 100644 --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer.pass.cpp @@ -75,6 +75,10 @@ TEST_CONSTEXPR_CXX23 void test_pointer() { } if (!TEST_IS_CONSTANT_EVALUATED) assert(A::count == 0); +// TODO: Remove this check once https://llvm.org/PR154567 is fixed +#if TEST_STD_VER >= 23 && defined(TEST_COMPILER_CLANG) + if (!TEST_IS_CONSTANT_EVALUATED) +#endif { A* p = newValue(expect_alive); if (!TEST_IS_CONSTANT_EVALUATED) diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp index b7cc12350027b..f7390ef5eb5d2 100644 --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp @@ -58,15 +58,18 @@ void test() { { { std::unique_ptr ptr(new WithCookie[5]); + assert(&ptr[1] == ptr.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr::operator[](index): index out of range"); } { std::unique_ptr ptr = std::make_unique(5); + assert(&ptr[1] == ptr.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr::operator[](index): index out of range"); } #if TEST_STD_VER >= 20 { std::unique_ptr ptr = std::make_unique_for_overwrite(5); + assert(&ptr[1] == ptr.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(ptr[6] = WithCookie(), "unique_ptr::operator[](index): index out of range"); } #endif @@ -82,11 +85,13 @@ void test() { { { std::unique_ptr ptr = std::make_unique(5); + assert(&ptr[1] == ptr.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr::operator[](index): index out of range"); } # if TEST_STD_VER >= 20 { std::unique_ptr ptr = std::make_unique_for_overwrite(5); + assert(&ptr[1] == ptr.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(ptr[6] = NoCookie(), "unique_ptr::operator[](index): index out of range"); } # endif @@ -101,6 +106,7 @@ void test() { { std::unique_ptr ptr = std::make_unique(5); std::unique_ptr other(std::move(ptr)); + assert(&other[1] == other.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr::operator[](index): index out of range"); } @@ -109,6 +115,7 @@ void test() { std::unique_ptr ptr = std::make_unique(5); std::unique_ptr other; other = std::move(ptr); + assert(&other[1] == other.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr::operator[](index): index out of range"); } @@ -116,6 +123,7 @@ void test() { { std::unique_ptr ptr = std::make_unique(5); std::unique_ptr other(std::move(ptr)); + assert(&other[1] == other.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr::operator[](index): index out of range"); } @@ -124,6 +132,7 @@ void test() { std::unique_ptr ptr = std::make_unique(5); std::unique_ptr other; other = std::move(ptr); + assert(&other[1] == other.get() + 1); // ensure no assertion TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr::operator[](index): index out of range"); } }); @@ -144,6 +153,34 @@ struct WithCookie { char padding[Size]; }; +template +struct alignas(128) OveralignedNoCookie { + char padding[Size]; +}; + +template +struct alignas(128) OveralignedWithCookie { + OveralignedWithCookie() = default; + OveralignedWithCookie(OveralignedWithCookie const&) {} + OveralignedWithCookie& operator=(OveralignedWithCookie const&) { return *this; } + ~OveralignedWithCookie() {} + char padding[Size]; +}; + +// These types have a different ABI alignment (alignof) and preferred alignment (__alignof) on some platforms. +// Make sure things work with these types because array cookies can be sensitive to preferred alignment on some +// platforms. +struct WithCookiePreferredAlignment { + WithCookiePreferredAlignment() = default; + WithCookiePreferredAlignment(WithCookiePreferredAlignment const&) {} + WithCookiePreferredAlignment& operator=(WithCookiePreferredAlignment const&) { return *this; } + ~WithCookiePreferredAlignment() {} + long double data; +}; +struct NoCookiePreferredAlignment { + long double data; +}; + int main(int, char**) { test, NoCookie<1>>(); test, NoCookie<2>>(); @@ -153,7 +190,18 @@ int main(int, char**) { test, NoCookie<16>>(); test, NoCookie<32>>(); test, NoCookie<256>>(); + + test, OveralignedNoCookie<1>>(); + test, OveralignedNoCookie<2>>(); + test, OveralignedNoCookie<3>>(); + test, OveralignedNoCookie<4>>(); + test, OveralignedNoCookie<8>>(); + test, OveralignedNoCookie<16>>(); + test, OveralignedNoCookie<32>>(); + test, OveralignedNoCookie<256>>(); + test(); + test(); return 0; } diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp index 142da1d820d9a..6111138726dbc 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -173,6 +173,11 @@ void test_vector_bool() { assert(std::get<0>(v) == true); } +struct ConvertibleFromAny { + template + ConvertibleFromAny(V) {} +}; + int main(int, char**) { test_T_ctor_basic(); test_T_ctor_noexcept(); @@ -180,5 +185,16 @@ int main(int, char**) { test_no_narrowing_check_for_class_types(); test_construction_with_repeated_types(); test_vector_bool(); + + { // Check that the constraints are evaluated lazily (see https://github.com/llvm/llvm-project/issues/151328) + struct Matcher { + Matcher() {} + Matcher(std::variant) {} + }; + + Matcher vec; + [[maybe_unused]] Matcher m = std::move(vec); + } + return 0; } diff --git a/libcxx/test/support/check_assertion.h b/libcxx/test/support/check_assertion.h index a279400d651b4..8416de76cfd61 100644 --- a/libcxx/test/support/check_assertion.h +++ b/libcxx/test/support/check_assertion.h @@ -44,15 +44,32 @@ static constexpr const char* Marker = "###"; using MatchResult = std::pair; using Matcher = std::function; -MatchResult MatchAssertionMessage(const std::string& text, std::string_view expected_message) { +// Using the marker makes matching more precise, but we cannot output the marker when the `observe` semantic is used +// (because it doesn't allow customizing the logging function). If the marker is not available, fall back to using less +// precise matching by just the error message. +MatchResult MatchAssertionMessage(const std::string& text, std::string_view expected_message, bool use_marker) { // Extract information from the error message. This has to stay synchronized with how we format assertions in the // library. - std::regex assertion_format(".*###\\n(.*):(\\d+): assertion (.*) failed: (.*)\\n###"); + std::string assertion_format_string = [&] { + if (use_marker) + return (".*###\\n(.*):(\\d+): libc\\+\\+ Hardening assertion (.*) failed: (.*)\\n###"); + return ("(.*):(\\d+): libc\\+\\+ Hardening assertion (.*) failed: (.*)\\n"); + }(); + std::regex assertion_format(assertion_format_string); std::smatch match_result; - bool has_match = std::regex_match(text, match_result, assertion_format); - assert(has_match); - assert(match_result.size() == 5); + // If a non-terminating assertion semantic is used, more than one assertion might be triggered before the process + // dies, so we cannot expect the entire target string to match. + bool has_match = std::regex_search(text, match_result, assertion_format); + if (!has_match || match_result.size() != 5) { + std::stringstream matching_error; + matching_error // + << "Failed to parse the assertion message.\n" // + << "Using marker: " << use_marker << "\n" // + << "Expected message: '" << expected_message.data() << "'\n" // + << "Stderr contents: '" << text.c_str() << "'\n"; + return MatchResult(/*success=*/false, matching_error.str()); + } const std::string& file = match_result[1]; int line = std::stoi(match_result[2]); @@ -72,9 +89,9 @@ MatchResult MatchAssertionMessage(const std::string& text, std::string_view expe return MatchResult(/*success=*/true, /*maybe_error=*/""); } -Matcher MakeAssertionMessageMatcher(std::string_view assertion_message) { +Matcher MakeAssertionMessageMatcher(std::string_view assertion_message, bool use_marker = true) { return [=](const std::string& text) { // - return MatchAssertionMessage(text, assertion_message); + return MatchAssertionMessage(text, assertion_message, use_marker); }; } @@ -85,13 +102,17 @@ Matcher MakeAnyMatcher() { } enum class DeathCause { - // Valid causes + // Valid causes. VerboseAbort = 1, StdAbort, StdTerminate, Trap, - // Invalid causes + // Causes that might be invalid or might stem from undefined behavior (relevant for non-terminating assertion + // semantics). DidNotDie, + Segfault, + ArithmeticError, + // Always invalid causes. SetupFailure, Unknown }; @@ -108,6 +129,16 @@ bool IsValidCause(DeathCause cause) { } } +bool IsTestSetupErrorCause(DeathCause cause) { + switch (cause) { + case DeathCause::SetupFailure: + case DeathCause::Unknown: + return true; + default: + return false; + } +} + std::string ToString(DeathCause cause) { switch (cause) { case DeathCause::VerboseAbort: @@ -120,10 +151,14 @@ std::string ToString(DeathCause cause) { return "trap"; case DeathCause::DidNotDie: return ""; + case DeathCause::Segfault: + return ""; + case DeathCause::ArithmeticError: + return ""; case DeathCause::SetupFailure: - return ""; + return ""; case DeathCause::Unknown: - return ""; + return ""; } assert(false && "Unreachable"); @@ -225,9 +260,38 @@ class DeathTest { return DeathTestResult(Outcome::Success, cause); } - void PrintFailureDetails(std::string_view failure_description, std::string_view stmt, DeathCause cause) const { - std::fprintf( - stderr, "Failure: EXPECT_DEATH( %s ) failed!\n(reason: %s)\n\n", stmt.data(), failure_description.data()); + // When non-terminating assertion semantics are used, the program will invoke UB which might or might not crash the + // process; we make sure that the execution produces the expected error message but otherwise consider the test run + // successful whether the child process dies or not. + template + DeathTestResult RunWithoutGuaranteedDeath(Func&& func, const Matcher& matcher) { + std::signal(SIGABRT, [](int) { StopChildProcess(DeathCause::StdAbort); }); + std::set_terminate([] { StopChildProcess(DeathCause::StdTerminate); }); + + DeathCause cause = Run(func); + + if (IsTestSetupErrorCause(cause)) { + return DeathTestResult(Outcome::InvalidCause, cause, ToString(cause)); + } + + MatchResult match_result = matcher(GetChildStdErr()); + if (!match_result.first) { + auto failure_description = std::string("Child produced a different error message\n") + match_result.second; + return DeathTestResult(Outcome::UnexpectedErrorMessage, cause, failure_description); + } + + return DeathTestResult(Outcome::Success, cause); + } + + void PrintFailureDetails(std::string_view invocation, + std::string_view failure_description, + std::string_view stmt, + DeathCause cause) const { + std::fprintf(stderr, + "Failure: %s( %s ) failed!\n(reason: %s)\n\n", + invocation.data(), + stmt.data(), + failure_description.data()); if (cause != DeathCause::Unknown) { std::fprintf(stderr, "child exit code: %d\n", GetChildExitCode()); @@ -311,10 +375,16 @@ class DeathTest { if (WIFSIGNALED(status_value)) { exit_code_ = WTERMSIG(status_value); - // `__builtin_trap` generqtes `SIGILL` on x86 and `SIGTRAP` on ARM. + // `__builtin_trap` generates `SIGILL` on x86 and `SIGTRAP` on ARM. if (exit_code_ == SIGILL || exit_code_ == SIGTRAP) { return DeathCause::Trap; } + if (exit_code_ == SIGSEGV) { + return DeathCause::Segfault; + } + if (exit_code_ == SIGFPE) { + return DeathCause::ArithmeticError; + } } return DeathCause::Unknown; @@ -357,7 +427,7 @@ bool ExpectDeath( DeathTest test_case; DeathTestResult test_result = test_case.Run(expected_causes, func, matcher); if (!test_result.success()) { - test_case.PrintFailureDetails(test_result.failure_description(), stmt, test_result.cause()); + test_case.PrintFailureDetails("EXPECT_DEATH", test_result.failure_description(), stmt, test_result.cause()); } return test_result.success(); @@ -378,6 +448,22 @@ bool ExpectDeath(DeathCause expected_cause, const char* stmt, Func&& func) { return ExpectDeath(std::array{expected_cause}, stmt, func, MakeAnyMatcher()); } +template +bool ExpectLog(const char* stmt, Func&& func, const Matcher& matcher) { + DeathTest test_case; + DeathTestResult test_result = test_case.RunWithoutGuaranteedDeath(func, matcher); + if (!test_result.success()) { + test_case.PrintFailureDetails("EXPECT_LOG", test_result.failure_description(), stmt, test_result.cause()); + } + + return test_result.success(); +} + +template +bool ExpectLog(const char* stmt, Func&& func) { + return ExpectLog(stmt, func, MakeAnyMatcher()); +} + // clang-format off /// Assert that the specified expression aborts with the expected cause and, optionally, error message. @@ -392,13 +478,28 @@ bool ExpectDeath(DeathCause expected_cause, const char* stmt, Func&& func) { #define EXPECT_STD_TERMINATE(...) \ assert( ExpectDeath(DeathCause::StdTerminate, #__VA_ARGS__, __VA_ARGS__) ) -#if defined(_LIBCPP_HARDENING_MODE) && _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +#if defined(_LIBCPP_ASSERTION_SEMANTIC) + +#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE #define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \ assert(( ExpectDeath(DeathCause::VerboseAbort, #expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message)) )) +#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE +#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \ + assert(( ExpectDeath(DeathCause::Trap, #expr, [&]() { (void)(expr); }) )) +#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE +#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \ + assert(( ExpectLog(#expr, [&]() { (void)(expr); }, MakeAssertionMessageMatcher(message, /*use_marker=*/false)) )) +#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE +#define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \ + assert(( ExpectLog(#expr, [&]() { (void)(expr); }) )) +#else +#error "Unknown value for _LIBCPP_ASSERTION_SEMANTIC" +#endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE + #else #define TEST_LIBCPP_ASSERT_FAILURE(expr, message) \ assert(( ExpectDeath(DeathCause::Trap, #expr, [&]() { (void)(expr); }) )) -#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +#endif // defined(_LIBCPP_ASSERTION_SEMANTIC) // clang-format on diff --git a/libcxx/test/support/is_transparent.h b/libcxx/test/support/is_transparent.h index 700c894a8b60f..4b2a458f574aa 100644 --- a/libcxx/test/support/is_transparent.h +++ b/libcxx/test/support/is_transparent.h @@ -36,6 +36,17 @@ struct transparent_less_not_referenceable using is_transparent = void () const &; // it's a type; a weird one, but a type }; +// Prevent regression when empty base class optimization is not suitable. +// See https://github.com/llvm/llvm-project/issues/152543. +struct transparent_less_nonempty { + template + constexpr bool operator()(T&& t, U&& u) const { + return std::forward(t) < std::forward(u); + } + struct is_transparent { + } pad_; // making this comparator non-empty +}; + struct transparent_less_no_type { template diff --git a/libcxx/test/support/test.support/test_check_assertion.pass.cpp b/libcxx/test/support/test.support/test_check_assertion.pass.cpp index 4dfc5319aaf97..78e47b32cdd2b 100644 --- a/libcxx/test/support/test.support/test_check_assertion.pass.cpp +++ b/libcxx/test/support/test.support/test_check_assertion.pass.cpp @@ -53,7 +53,7 @@ bool TestDeathTest( } if (!maybe_failure_description.empty()) { - test_case.PrintFailureDetails(maybe_failure_description, stmt, test_result.cause()); + test_case.PrintFailureDetails("EXPECT_DEATH", maybe_failure_description, stmt, test_result.cause()); return false; } @@ -76,9 +76,9 @@ DeathCause assertion_death_cause = DeathCause::Trap; #endif int main(int, char**) { - auto fail_assert = [] { _LIBCPP_ASSERT(false, "Some message"); }; - Matcher good_matcher = MakeAssertionMessageMatcher("Some message"); - Matcher bad_matcher = MakeAssertionMessageMatcher("Bad expected message"); + [[maybe_unused]] auto fail_assert = [] { _LIBCPP_ASSERT(false, "Some message"); }; + Matcher good_matcher = MakeAssertionMessageMatcher("Some message"); + Matcher bad_matcher = MakeAssertionMessageMatcher("Bad expected message"); // Test the implementation of death tests. We're bypassing the assertions added by the actual `EXPECT_DEATH` macros // which allows us to test failure cases (where the assertion would fail) as well. @@ -89,16 +89,22 @@ int main(int, char**) { // Success -- trapping. TEST_DEATH_TEST(Outcome::Success, DeathCause::Trap, __builtin_trap()); + // `_LIBCPP_ASSERT` does not terminate the program if the `observe` semantic is used, so these tests would fail with + // `DidNotDie` cause. +#if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE + // Success -- assertion failure with any matcher. TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, MakeAnyMatcher(), fail_assert()); // Success -- assertion failure with a specific matcher. TEST_DEATH_TEST_MATCHES(Outcome::Success, assertion_death_cause, good_matcher, fail_assert()); -#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG // Failure -- error message doesn't match. TEST_DEATH_TEST_MATCHES(Outcome::UnexpectedErrorMessage, assertion_death_cause, bad_matcher, fail_assert()); -#endif +# endif + +#endif // _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE // Invalid cause -- child did not die. TEST_DEATH_TEST(Outcome::InvalidCause, DeathCause::DidNotDie, ((void)0)); @@ -125,7 +131,9 @@ int main(int, char**) { EXPECT_DEATH_MATCHES(simple_matcher, invoke_verbose_abort()); EXPECT_STD_ABORT(invoke_abort()); EXPECT_STD_TERMINATE([] { std::terminate(); }); +#if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE TEST_LIBCPP_ASSERT_FAILURE(fail_assert(), "Some message"); +#endif } return 0; diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot index d8b23be9a0323..57ecf1e49dbf2 100755 --- a/libcxx/utils/ci/run-buildbot +++ b/libcxx/utils/ci/run-buildbot @@ -442,6 +442,12 @@ generic-hardening-mode-extensive) check-runtimes check-abi-list ;; +generic-hardening-mode-extensive-observe-semantic) + clean + generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-hardening-mode-extensive-observe-semantic.cmake" + check-runtimes + check-abi-list +;; generic-hardening-mode-debug) clean generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-hardening-mode-debug.cmake" diff --git a/libcxx/utils/libcxx/sym_check/util.py b/libcxx/utils/libcxx/sym_check/util.py index fc7ba4244ab5a..dbc886f29ddea 100644 --- a/libcxx/utils/libcxx/sym_check/util.py +++ b/libcxx/utils/libcxx/sym_check/util.py @@ -95,7 +95,7 @@ def is_xcoff_or_big_ar(filename): with open(filename, "rb") as f: magic_bytes = f.read(7) return ( - magic_bytes[:4] in [b"\x01DF", b"\x01F7"] # XCOFF32 # XCOFF64 + magic_bytes[:2] in [b"\x01\xDF", b"\x01\xF7"] # XCOFF32 # XCOFF64 or magic_bytes == b"" ) diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index adfb2a9f69508..81c613421a465 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -361,6 +361,7 @@ def getSuitableClangTidy(cfg): AddFeature("libcpp-has-no-incomplete-pstl"), AddFeature("libcpp-has-no-experimental-tzdb"), AddFeature("libcpp-has-no-experimental-syncstream"), + AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"), ], ), # TODO: This can be improved once we use a version of GoogleBenchmark that supports the dry-run mode. @@ -454,5 +455,24 @@ def getSuitableClangTidy(cfg): help="Whether to test the main or C++03-specific headers. Only changes behaviour when std=c++03.", actions=lambda enabled: [] if not enabled else [AddFlag("-D_LIBCPP_USE_FROZEN_CXX03_HEADERS"), AddFeature("FROZEN-CXX03-HEADERS-FIXME")], ), + Parameter( + name='assertion_semantic', + choices=["ignore", "observe", "quick_enforce", "enforce", "undefined"], + type=str, + default="undefined", + help="Whether to override the assertion semantic used by hardening. This is only meaningful when running the " + "tests against libc++ with hardening enabled. By default, no assertion semantic is specified explicitly, so " + "the default one will be used (depending on the hardening mode).", + actions=lambda assertion_semantic: filter( + None, + [ + AddCompileFlag("-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_IGNORE") if assertion_semantic == "ignore" else None, + AddCompileFlag("-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_OBSERVE") if assertion_semantic == "observe" else None, + AddCompileFlag("-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE") if assertion_semantic == "quick_enforce" else None, + AddCompileFlag("-D_LIBCPP_ASSERTION_SEMANTIC=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE") if assertion_semantic == "enforce" else None, + AddFeature("libcpp-assertion-semantic={}".format(assertion_semantic)) if assertion_semantic != "undefined" else None, + ], + ), + ), ] # fmt: on diff --git a/libcxx/vendor/llvm/default_assertion_handler.in b/libcxx/vendor/llvm/default_assertion_handler.in index f115658f9f3c6..d352405e905b5 100644 --- a/libcxx/vendor/llvm/default_assertion_handler.in +++ b/libcxx/vendor/llvm/default_assertion_handler.in @@ -16,6 +16,7 @@ # include <__cxx03/__verbose_trap> #else # include <__config> +# include <__log_hardening_failure> # include <__verbose_abort> # include <__verbose_trap> #endif @@ -24,14 +25,40 @@ # pragma GCC system_header #endif -#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) -# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message) +// Keep the old implementation that doesn't support assertion semantics for backward compatibility with the frozen C++03 +// mode. +# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message) +# else +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message) +# endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG #else -# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message) +# if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE +# define _LIBCPP_ASSERTION_HANDLER(message) ((void)0) + +# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_HARDENING_FAILURE(message) + +# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message) + +# elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE +# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_ABORT("%s", message) + +# else + +# error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \ +_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \ +_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \ +_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \ +_LIBCPP_ASSERTION_SEMANTIC_ENFORCE + +# endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE -#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG +#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP___ASSERTION_HANDLER diff --git a/libcxxabi/src/demangle/DemangleConfig.h b/libcxxabi/src/demangle/DemangleConfig.h index 06fd223f5553f..7904e9d1eb133 100644 --- a/libcxxabi/src/demangle/DemangleConfig.h +++ b/libcxxabi/src/demangle/DemangleConfig.h @@ -19,6 +19,14 @@ #include "../abort_message.h" #endif +#ifndef _LIBCPP_LOG_HARDENING_FAILURE +// Libc++abi does not have any functionality to log and continue, so we drop +// error messages when we build the demangler with `observe` assertion semantic. +// Once the layering with libc++ is improved, this could use the libc++ +// functionality to log hardening failures. +#define _LIBCPP_LOG_HARDENING_FAILURE(message) ((void)0) +#endif + #include #ifdef _MSC_VER diff --git a/libunwind/src/Unwind-seh.cpp b/libunwind/src/Unwind-seh.cpp index 8b83f10615f22..110c5987c3f1a 100644 --- a/libunwind/src/Unwind-seh.cpp +++ b/libunwind/src/Unwind-seh.cpp @@ -174,7 +174,8 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, } // FIXME: Indicate target frame in foreign case! // phase 2: the clean up phase - RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable); + RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, disp->ContextRecord, + disp->HistoryTable); _LIBUNWIND_ABORT("RtlUnwindEx() failed"); case _URC_INSTALL_CONTEXT: { // If we were called by __libunwind_seh_personality(), indicate that diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 55db035e62040..9a1afd3721f5a 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -173,7 +173,8 @@ bool DwarfFDECache::_registeredForDyldUnloads = false; #endif template -typename A::pint_t DwarfFDECache::findFDE(pint_t mh, pint_t pc) { +typename DwarfFDECache::pint_t DwarfFDECache::findFDE(pint_t mh, + pint_t pc) { pint_t result = 0; _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 5e199188945df..1bcd205be260d 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -1044,9 +1044,10 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) lw $27, (4 * 27)($4) lw $28, (4 * 28)($4) lw $29, (4 * 29)($4) - lw $30, (4 * 30)($4) // load new pc into ra lw $31, (4 * 32)($4) + // MIPS 1 has load delay slot. Ensure lw $31 and jr are separated by an instruction. + lw $30, (4 * 30)($4) // jump to ra, load a0 in the delay slot jr $31 lw $4, (4 * 4)($4) @@ -1082,11 +1083,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) ld $2, (8 * 2)($4) ld $3, (8 * 3)($4) // skip a0 for now - .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 + .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29 ld $\i, (8 * \i)($4) .endr // load new pc into ra ld $31, (8 * 32)($4) + // MIPS 1 has load delay slot. Ensure lw $31 and jr are separated by an instruction. + ld $30, (8 * 30)($4) // jump to ra, load a0 in the delay slot jr $31 ld $4, (8 * 4)($4) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 01752cdc6a9da..cfb33daa024a7 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -939,7 +939,7 @@ void ECCodeMapChunk::writeTo(uint8_t *buf) const { auto table = reinterpret_cast(buf); for (uint32_t i = 0; i < map.size(); i++) { const ECCodeMapEntry &entry = map[i]; - uint32_t start = entry.first->getRVA(); + uint32_t start = entry.first->getRVA() & ~0xfff; table[i].StartOffset = start | entry.type; table[i].Length = entry.last->getRVA() + entry.last->getSize() - start; } diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 79b63e5b7236f..91b6e632fa7ed 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -192,6 +192,18 @@ struct Configuration { // Used for /lldltocachepolicy=policy llvm::CachePruningPolicy ltoCachePolicy; + // Used for /thinlto-distributor: + StringRef dtltoDistributor; + + // Used for /thinlto-distributor-arg: + llvm::SmallVector dtltoDistributorArgs; + + // Used for /thinlto-remote-compiler: + StringRef dtltoCompiler; + + // Used for /thinlto-remote-compiler-arg: + llvm::SmallVector dtltoCompilerArgs; + // Used for /opt:[no]ltodebugpassmanager bool ltoDebugPassManager = false; @@ -307,7 +319,7 @@ struct Configuration { bool warnDebugInfoUnusable = true; bool warnLongSectionNames = true; bool warnStdcallFixup = true; - bool warnExportedDllMain = true; + bool warnImportedDllMain = true; bool incremental = true; bool integrityCheck = false; bool killAt = false; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index c327da28ce138..10bc898244a4a 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -244,40 +244,36 @@ static const uint8_t thunkX64[] = { }; static const uint8_t tailMergeX64[] = { - 0x51, // push rcx - 0x52, // push rdx - 0x41, 0x50, // push r8 - 0x41, 0x51, // push r9 - 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h - 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0 - 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1 - 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2 - 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3 - 0x48, 0x8B, 0xD0, // mov rdx, rax - 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...] - 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2 - 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp] - 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h] - 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h] - 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h] - 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h - 0x41, 0x59, // pop r9 - 0x41, 0x58, // pop r8 - 0x5A, // pop rdx - 0x59, // pop rcx - 0xFF, 0xE0, // jmp rax + 0x48, 0x89, 0x4C, 0x24, 0x08, // mov qword ptr [rsp+8], rcx + 0x48, 0x89, 0x54, 0x24, 0x10, // mov qword ptr [rsp+10h], rdx + 0x4C, 0x89, 0x44, 0x24, 0x18, // mov qword ptr [rsp+18h], r8 + 0x4C, 0x89, 0x4C, 0x24, 0x20, // mov qword ptr [rsp+20h], r9 + 0x48, 0x83, 0xEC, 0x68, // sub rsp, 68h + 0x66, 0x0F, 0x7F, 0x44, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm0 + 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm1 + 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x40, // movdqa xmmword ptr [rsp+40h], xmm2 + 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x50, // movdqa xmmword ptr [rsp+50h], xmm3 + 0x48, 0x8B, 0xD0, // mov rdx, rax + 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...] + 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2 + 0x66, 0x0F, 0x6F, 0x44, 0x24, 0x20, // movdqa xmm0, xmmword ptr [rsp+20h] + 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x30, // movdqa xmm1, xmmword ptr [rsp+30h] + 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x40, // movdqa xmm2, xmmword ptr [rsp+40h] + 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x50, // movdqa xmm3, xmmword ptr [rsp+50h] + 0x48, 0x8B, 0x4C, 0x24, 0x70, // mov rcx, qword ptr [rsp+70h] + 0x48, 0x8B, 0x54, 0x24, 0x78, // mov rdx, qword ptr [rsp+78h] + 0x4C, 0x8B, 0x84, 0x24, 0x80, 0, 0, 0, // mov r8, qword ptr [rsp+80h] + 0x4C, 0x8B, 0x8C, 0x24, 0x88, 0, 0, 0, // mov r9, qword ptr [rsp+88h] + 0x48, 0x83, 0xC4, 0x68, // add rsp, 68h + 0xFF, 0xE0, // jmp rax }; static const uint8_t tailMergeUnwindInfoX64[] = { 0x01, // Version=1, Flags=UNW_FLAG_NHANDLER - 0x0a, // Size of prolog - 0x05, // Count of unwind codes + 0x18, // Size of prolog + 0x01, // Count of unwind codes 0x00, // No frame register - 0x0a, 0x82, // Offset 0xa: UWOP_ALLOC_SMALL(0x48) - 0x06, 0x02, // Offset 6: UWOP_ALLOC_SMALL(8) - 0x04, 0x02, // Offset 4: UWOP_ALLOC_SMALL(8) - 0x02, 0x02, // Offset 2: UWOP_ALLOC_SMALL(8) - 0x01, 0x02, // Offset 1: UWOP_ALLOC_SMALL(8) + 0x18, 0xC2, // Offset 0x18: UWOP_ALLOC_SMALL(0x68) 0x00, 0x00 // Padding to align on 32-bits }; @@ -324,30 +320,34 @@ static const uint8_t thunkARM64[] = { }; static const uint8_t tailMergeARM64[] = { - 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]! + 0xfd, 0x7b, 0xb2, 0xa9, // stp x29, x30, [sp, #-224]! 0xfd, 0x03, 0x00, 0x91, // mov x29, sp 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16] 0xe2, 0x0f, 0x02, 0xa9, // stp x2, x3, [sp, #32] 0xe4, 0x17, 0x03, 0xa9, // stp x4, x5, [sp, #48] 0xe6, 0x1f, 0x04, 0xa9, // stp x6, x7, [sp, #64] - 0xe0, 0x87, 0x02, 0xad, // stp q0, q1, [sp, #80] - 0xe2, 0x8f, 0x03, 0xad, // stp q2, q3, [sp, #112] - 0xe4, 0x97, 0x04, 0xad, // stp q4, q5, [sp, #144] - 0xe6, 0x9f, 0x05, 0xad, // stp q6, q7, [sp, #176] + 0xe8, 0x2b, 0x00, 0xf9, // str x8, [sp, #80] + 0xe0, 0x07, 0x03, 0xad, // stp q0, q1, [sp, #96] + 0xe2, 0x0f, 0x04, 0xad, // stp q2, q3, [sp, #128] + 0xe4, 0x17, 0x05, 0xad, // stp q4, q5, [sp, #160] + 0xe6, 0x1f, 0x06, 0xad, // stp q6, q7, [sp, #192] 0xe1, 0x03, 0x11, 0xaa, // mov x1, x17 0x00, 0x00, 0x00, 0x90, // adrp x0, #0 DELAY_IMPORT_DESCRIPTOR 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR - 0x00, 0x00, 0x00, 0x94, // bl #0 __delayLoadHelper2 + 0x02, 0x00, 0x00, 0x90, // adrp x2, #0 __delayLoadHelper2 + 0x42, 0x00, 0x00, 0x91, // add x2, x2, #0 :lo12:__delayLoadHelper2 + 0x40, 0x00, 0x3f, 0xd6, // blr x2 0xf0, 0x03, 0x00, 0xaa, // mov x16, x0 - 0xe6, 0x9f, 0x45, 0xad, // ldp q6, q7, [sp, #176] - 0xe4, 0x97, 0x44, 0xad, // ldp q4, q5, [sp, #144] - 0xe2, 0x8f, 0x43, 0xad, // ldp q2, q3, [sp, #112] - 0xe0, 0x87, 0x42, 0xad, // ldp q0, q1, [sp, #80] + 0xe6, 0x1f, 0x46, 0xad, // ldp q6, q7, [sp, #192] + 0xe4, 0x17, 0x45, 0xad, // ldp q4, q5, [sp, #160] + 0xe2, 0x0f, 0x44, 0xad, // ldp q2, q3, [sp, #128] + 0xe0, 0x07, 0x43, 0xad, // ldp q0, q1, [sp, #96] + 0xe8, 0x2b, 0x40, 0xf9, // ldr x8, [sp, #80] 0xe6, 0x1f, 0x44, 0xa9, // ldp x6, x7, [sp, #64] 0xe4, 0x17, 0x43, 0xa9, // ldp x4, x5, [sp, #48] 0xe2, 0x0f, 0x42, 0xa9, // ldp x2, x3, [sp, #32] 0xe0, 0x07, 0x41, 0xa9, // ldp x0, x1, [sp, #16] - 0xfd, 0x7b, 0xcd, 0xa8, // ldp x29, x30, [sp], #208 + 0xfd, 0x7b, 0xce, 0xa8, // ldp x29, x30, [sp], #224 0x00, 0x02, 0x1f, 0xd6, // br x16 }; @@ -378,8 +378,8 @@ class TailMergeChunkX64 : public NonSectionCodeChunk { void writeTo(uint8_t *buf) const override { memcpy(buf, tailMergeX64, sizeof(tailMergeX64)); - write32le(buf + 39, desc->getRVA() - rva - 43); - write32le(buf + 44, helper->getRVA() - rva - 48); + write32le(buf + 54, desc->getRVA() - rva - 58); + write32le(buf + 59, helper->getRVA() - rva - 63); } Chunk *desc = nullptr; @@ -558,10 +558,12 @@ class TailMergeChunkARM64 : public NonSectionCodeChunk { void writeTo(uint8_t *buf) const override { memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64)); - applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12); - applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0); - if (helper) - applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52); + applyArm64Addr(buf + 48, desc->getRVA(), rva + 48, 12); + applyArm64Imm(buf + 52, desc->getRVA() & 0xfff, 0); + if (helper) { + applyArm64Addr(buf + 56, helper->getRVA(), rva + 56, 12); + applyArm64Imm(buf + 60, helper->getRVA() & 0xfff, 0); + } } Chunk *desc = nullptr; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 283aeed1a19cd..570b8f9d05906 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -274,8 +274,13 @@ void LinkerDriver::addBuffer(std::unique_ptr mb, make>(std::move(file)); // take ownership int memberIndex = 0; - for (MemoryBufferRef m : getArchiveMembers(ctx, archive)) - addArchiveBuffer(m, "", filename, memberIndex++); + for (MemoryBufferRef m : getArchiveMembers(ctx, archive)) { + if (!archive->isThin()) + addArchiveBuffer(m, "", filename, memberIndex++); + else + addThinArchiveBuffer(m, ""); + } + return; } addFile(make(ctx, mbref)); @@ -386,6 +391,14 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, Log(ctx) << "Loaded " << obj << " for " << symName; } +void LinkerDriver::addThinArchiveBuffer(MemoryBufferRef mb, StringRef symName) { + // Pass an empty string as the archive name and an offset of 0 so that + // the original filename is used as the buffer identifier. This is + // useful for DTLTO, where having the member identifier be the actual + // path on disk enables distribution of bitcode files during ThinLTO. + addArchiveBuffer(mb, symName, /*parentName=*/"", /*OffsetInArchive=*/0); +} + void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym, StringRef parentName) { @@ -422,11 +435,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, reportBufferError(errorCodeToError(mbOrErr.second), childName); llvm::TimeTraceScope timeScope("Archive: ", mbOrErr.first->getBufferIdentifier()); - // Pass empty string as archive name so that the original filename is - // used as the buffer identifier. - ctx.driver.addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), - toCOFFString(ctx, sym), "", - /*OffsetInArchive=*/0); + ctx.driver.addThinArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), + toCOFFString(ctx, sym)); }); } @@ -1643,8 +1653,8 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { config->warnLocallyDefinedImported = false; else if (s == "longsections") config->warnLongSectionNames = false; - else if (s == "exporteddllmain") - config->warnExportedDllMain = false; + else if (s == "importeddllmain") + config->warnImportedDllMain = false; // Other warning numbers are ignored. } } @@ -2088,6 +2098,23 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { Fatal(ctx) << "/manifestinput: requires /manifest:embed"; } + // Handle /thinlto-distributor: + config->dtltoDistributor = args.getLastArgValue(OPT_thinlto_distributor); + + // Handle /thinlto-distributor-arg: + for (auto *arg : args.filtered(OPT_thinlto_distributor_arg)) + config->dtltoDistributorArgs.push_back(arg->getValue()); + + // Handle /thinlto-remote-compiler: + config->dtltoCompiler = args.getLastArgValue(OPT_thinlto_compiler); + if (!config->dtltoDistributor.empty() && config->dtltoCompiler.empty()) + Err(ctx) << "A value must be specified for /thinlto-remote-compiler if " + "/thinlto-distributor is specified."; + + // Handle /thinlto-remote-compiler-arg: + for (auto *arg : args.filtered(OPT_thinlto_compiler_arg)) + config->dtltoCompilerArgs.push_back(arg->getValue()); + // Handle /dwodir config->dwoDir = args.getLastArgValue(OPT_dwodir); @@ -2527,28 +2554,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { e.symbolName = symtab.mangleMaybe(e.sym); } - // Add weak aliases. Weak aliases is a mechanism to give remaining - // undefined symbols final chance to be resolved successfully. - for (auto pair : symtab.alternateNames) { - StringRef from = pair.first; - StringRef to = pair.second; - Symbol *sym = symtab.find(from); - if (!sym) - continue; - if (auto *u = dyn_cast(sym)) { - if (u->weakAlias) { - // On ARM64EC, anti-dependency aliases are treated as undefined - // symbols unless a demangled symbol aliases a defined one, which - // is part of the implementation. - if (!symtab.isEC() || !u->isAntiDep) - continue; - if (!isa(u->weakAlias) && - !isArm64ECMangledFunctionName(u->getName())) - continue; - } - u->setWeakAlias(symtab.addUndefined(to)); - } - } + symtab.resolveAlternateNames(); }); ctx.forEachActiveSymtab([&](SymbolTable &symtab) { diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 14c97a98875bf..5a9bd5c6d9682 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -173,6 +173,7 @@ class LinkerDriver { bool lazy); void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName, StringRef parentName, uint64_t offsetInArchive); + void addThinArchiveBuffer(MemoryBufferRef mbref, StringRef symName); void enqueueTask(std::function task); bool run(); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index d8b41c7f45400..5ef41c4c0a086 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -387,7 +387,7 @@ std::string LinkerDriver::createDefaultXml() { << "\n"; if (ctx.config.manifestUAC) { - os << " \n" + os << " \n" << " \n" << " \n" << " getFileName() + ": could not get the buffer for a child buffer of the archive"); if (identify_magic(mb.getBuffer()) == file_magic::coff_import_library) { - if (ctx.config.warnExportedDllMain) { + if (ctx.config.warnImportedDllMain) { // We won't place DllMain symbols in the symbol table if they are // coming from a import library. This message can be ignored with the flag - // '/ignore:exporteddllmain' + // '/ignore:importeddllmain' Warn(ctx) << file->getFileName() - << ": skipping exported DllMain symbol [exporteddllmain]\nNOTE: this " + << ": skipping imported DllMain symbol [importeddllmain]\nNOTE: this " "might be a mistake when the DLL/library was produced."; } skipDllMain = true; @@ -204,14 +202,24 @@ void ArchiveFile::parse() { } } - // Read the symbol table to construct Lazy objects. bool skipDllMain = false; + StringRef mangledDllMain, impMangledDllMain; + + // The calls below will fail if we haven't set the machine type yet. Instead + // of failing, it is preferable to skip this "imported DllMain" check if we + // don't know the machine type at this point. + if (!file->isEmpty() && ctx.config.machine != IMAGE_FILE_MACHINE_UNKNOWN) { + mangledDllMain = archiveSymtab->mangle("DllMain"); + impMangledDllMain = uniqueSaver().save("__imp_" + mangledDllMain); + } + + // Read the symbol table to construct Lazy objects. for (const Archive::Symbol &sym : file->symbols()) { - // If the DllMain symbol was exported by mistake, skip importing it - // otherwise we might end up with a import thunk in the final binary which - // is wrong. - if (sym.getName() == "__imp_DllMain" || sym.getName() == "DllMain") { - if (fixupDllMain(ctx, file.get(), sym, skipDllMain)) + // If an import library provides the DllMain symbol, skip importing it, as + // we should be using our own DllMain, not another DLL's DllMain. + if (!mangledDllMain.empty() && (sym.getName() == mangledDllMain || + sym.getName() == impMangledDllMain)) { + if (skipDllMain || fixupDllMain(ctx, file.get(), sym, skipDllMain)) continue; } archiveSymtab->addLazyArchive(this, sym); diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp index 2a4d07cc2d015..1050874a1b10c 100644 --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -110,7 +110,16 @@ BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) { // Initialize ltoObj. lto::ThinBackend backend; - if (ctx.config.thinLTOIndexOnly) { + if (!ctx.config.dtltoDistributor.empty()) { + backend = lto::createOutOfProcessThinBackend( + llvm::hardware_concurrency(ctx.config.thinLTOJobs), + /*OnWrite=*/nullptr, + /*ShouldEmitIndexFiles=*/false, + /*ShouldEmitImportFiles=*/false, ctx.config.outputFile, + ctx.config.dtltoDistributor, ctx.config.dtltoDistributorArgs, + ctx.config.dtltoCompiler, ctx.config.dtltoCompilerArgs, + !ctx.config.saveTempsArgs.empty()); + } else if (ctx.config.thinLTOIndexOnly) { auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); }; backend = lto::createWriteIndexesThinBackend( llvm::hardware_concurrency(ctx.config.thinLTOJobs), diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index a887d7d351e18..2a82fb5cd8845 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -270,6 +270,17 @@ def thinlto_object_suffix_replace : P< def thinlto_prefix_replace: P< "thinlto-prefix-replace", "'old;new' replace old prefix with new prefix in ThinLTO outputs">; +def thinlto_distributor : P<"thinlto-distributor", + "Distributor to use for ThinLTO backend compilations. If specified, ThinLTO " + "backend compilations will be distributed">; +def thinlto_distributor_arg : P<"thinlto-distributor-arg", + "Arguments to pass to the ThinLTO distributor">; +def thinlto_compiler : P<"thinlto-remote-compiler", + "Compiler for the ThinLTO distributor to invoke for ThinLTO backend " + "compilations">; +def thinlto_compiler_arg : P<"thinlto-remote-compiler-arg", + "Compiler arguments for the ThinLTO distributor to pass for ThinLTO backend " + "compilations">; def lto_obj_path : P< "lto-obj-path", "output native object for merged LTO unit to this path">; diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index a54ea403ba2ec..94eeae2797971 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -1135,9 +1135,12 @@ static pdb::BulkPublic createPublic(COFFLinkerContext &ctx, Defined *def) { pub.setFlags(flags); OutputSection *os = ctx.getOutputSection(def->getChunk()); - assert(os && "all publics should be in final image"); - pub.Offset = def->getRVA() - os->getRVA(); - pub.Segment = os->sectionIndex; + assert((os || !def->getChunk()->getSize()) && + "all publics should be in final image"); + if (os) { + pub.Offset = def->getRVA() - os->getRVA(); + pub.Segment = os->sectionIndex; + } return pub; } diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 0062df5820e63..d15e0c24410c6 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -1344,6 +1344,44 @@ void SymbolTable::parseAlternateName(StringRef s) { alternateNames.insert(it, std::make_pair(from, to)); } +void SymbolTable::resolveAlternateNames() { + // Add weak aliases. Weak aliases is a mechanism to give remaining + // undefined symbols final chance to be resolved successfully. + for (auto pair : alternateNames) { + StringRef from = pair.first; + StringRef to = pair.second; + Symbol *sym = find(from); + if (!sym) + continue; + if (auto *u = dyn_cast(sym)) { + if (u->weakAlias) { + // On ARM64EC, anti-dependency aliases are treated as undefined + // symbols unless a demangled symbol aliases a defined one, which + // is part of the implementation. + if (!isEC() || !u->isAntiDep) + continue; + if (!isa(u->weakAlias) && + !isArm64ECMangledFunctionName(u->getName())) + continue; + } + + // Check if the destination symbol is defined. If not, skip it. + // It may still be resolved later if more input files are added. + // Also skip anti-dependency targets, as they can't be chained anyway. + Symbol *toSym = find(to); + if (!toSym) + continue; + auto toUndef = dyn_cast(toSym); + if (toUndef && (!toUndef->weakAlias || toUndef->isAntiDep)) + continue; + toSym->isUsedInRegularObj = true; + if (toSym->isLazy()) + forceLazy(toSym); + u->setWeakAlias(toSym); + } + } +} + // Parses /aligncomm option argument. void SymbolTable::parseAligncomm(StringRef s) { auto [name, align] = s.split(','); diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 15e2644a6f519..7eb067640dc85 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -69,6 +69,9 @@ class SymbolTable { // symbols and warn about imported local symbols. void resolveRemainingUndefines(); + // Try to resolve undefined symbols with alternate names. + void resolveAlternateNames(); + // Load lazy objects that are needed for MinGW automatic import and for // doing stdcall fixups. void loadMinGWSymbols(); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 076561807af47..ef9d051bf976e 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1553,7 +1553,7 @@ void Writer::createSymbolAndStringTable() { dthunk->wrappedSym->writtenToSymtab = true; if (std::optional sym = createSymbol(dthunk->wrappedSym)) { - if (d->getName().size() > COFF::NameSize) + if (dthunk->wrappedSym->getName().size() > COFF::NameSize) longNameSymbols.emplace_back(outputSymtab.size(), dthunk->wrappedSym->getName()); outputSymtab.push_back(*sym); diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 479131a24dcfc..9b33e78731c97 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -11,6 +11,7 @@ #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "Thunks.h" #include "lld/Common/ErrorHandler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/ELF.h" @@ -36,6 +37,10 @@ class Hexagon final : public TargetInfo { const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s, + int64_t a) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; void writePltHeader(uint8_t *buf) const override; @@ -63,6 +68,8 @@ Hexagon::Hexagon(Ctx &ctx) : TargetInfo(ctx) { tlsGotRel = R_HEX_TPREL_32; tlsModuleIndexRel = R_HEX_DTPMOD_32; tlsOffsetRel = R_HEX_DTPREL_32; + + needsThunks = true; } uint32_t Hexagon::calcEFlags() const { @@ -258,6 +265,46 @@ static uint32_t findMaskR16(Ctx &ctx, uint32_t insn) { static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); } +bool Hexagon::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + int64_t offset = dst - src; + switch (type) { + case llvm::ELF::R_HEX_B22_PCREL: + case llvm::ELF::R_HEX_PLT_B22_PCREL: + case llvm::ELF::R_HEX_GD_PLT_B22_PCREL: + case llvm::ELF::R_HEX_LD_PLT_B22_PCREL: + return llvm::isInt<22>(offset >> 2); + case llvm::ELF::R_HEX_B15_PCREL: + return llvm::isInt<15>(offset >> 2); + break; + case llvm::ELF::R_HEX_B13_PCREL: + return llvm::isInt<13>(offset >> 2); + break; + case llvm::ELF::R_HEX_B9_PCREL: + return llvm::isInt<9>(offset >> 2); + default: + return true; + } + llvm_unreachable("unsupported relocation"); +} + +bool Hexagon::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s, + int64_t a) const { + // Only check branch range for supported branch relocation types + switch (type) { + case R_HEX_B22_PCREL: + case R_HEX_PLT_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL: + case R_HEX_LD_PLT_B22_PCREL: + case R_HEX_B15_PCREL: + case R_HEX_B13_PCREL: + case R_HEX_B9_PCREL: + return !ctx.target->inBranchRange(type, branchAddr, s.getVA(ctx, a)); + default: + return false; + } +} + void Hexagon::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { switch (rel.type) { diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp index fe804cbb0e690..8802c8c2e7f01 100644 --- a/lld/ELF/Arch/LoongArch.cpp +++ b/lld/ELF/Arch/LoongArch.cpp @@ -46,6 +46,8 @@ class LoongArch final : public TargetInfo { private: void tlsdescToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const; void tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; + bool tryGotToPCRel(uint8_t *loc, const Relocation &rHi20, + const Relocation &rLo12, uint64_t secAddr) const; }; } // end anonymous namespace @@ -809,10 +811,13 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i, // address. // Meanwhile skip undefined, preemptible and STT_GNU_IFUNC symbols, because // these symbols may be resolve in runtime. + // Moreover, relaxation can only occur if the addends of both relocations are + // zero for GOT references. if (rHi20.type == R_LARCH_GOT_PC_HI20 && - (!rHi20.sym->isDefined() || rHi20.sym->isPreemptible || - rHi20.sym->isGnuIFunc() || - (ctx.arg.isPic && !cast(*rHi20.sym).section))) + (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() || + rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc() || + (ctx.arg.isPic && !cast(*rHi20.sym).section) || + rHi20.addend != 0 || rLo12.addend != 0)) return; uint64_t dest = 0; @@ -966,10 +971,16 @@ static bool relax(Ctx &ctx, InputSection &sec) { case R_LARCH_GOT_PC_HI20: case R_LARCH_TLS_GD_PC_HI20: case R_LARCH_TLS_LD_PC_HI20: - case R_LARCH_TLS_DESC_PC_HI20: // The overflow check for i+2 will be carried out in isPairRelaxable. - if (r.expr != RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC && - r.expr != R_RELAX_TLS_GD_TO_LE && isPairRelaxable(relocs, i)) + if (isPairRelaxable(relocs, i)) + relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove); + break; + case R_LARCH_TLS_DESC_PC_HI20: + if (r.expr == RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC || + r.expr == R_RELAX_TLS_GD_TO_LE) { + if (relaxable(relocs, i)) + remove = 4; + } else if (isPairRelaxable(relocs, i)) relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove); break; case R_LARCH_CALL36: @@ -987,6 +998,17 @@ static bool relax(Ctx &ctx, InputSection &sec) { isUInt<12>(r.sym->getVA(ctx, r.addend))) remove = 4; break; + case R_LARCH_TLS_DESC_PC_LO12: + if (relaxable(relocs, i) && + (r.expr == RE_LOONGARCH_RELAX_TLS_GD_TO_IE_PAGE_PC || + r.expr == R_RELAX_TLS_GD_TO_LE)) + remove = 4; + break; + case R_LARCH_TLS_DESC_LD: + if (relaxable(relocs, i) && r.expr == R_RELAX_TLS_GD_TO_LE && + isUInt<12>(r.sym->getVA(ctx, r.addend))) + remove = 4; + break; } // For all anchors whose offsets are <= r.offset, they are preceded by @@ -1135,6 +1157,78 @@ void LoongArch::tlsdescToLe(uint8_t *loc, const Relocation &rel, } } +// Try GOT indirection to PC relative optimization. +// From: +// * pcalau12i $a0, %got_pc_hi20(sym_got) +// * ld.w/d $a0, $a0, %got_pc_lo12(sym_got) +// To: +// * pcalau12i $a0, %pc_hi20(sym) +// * addi.w/d $a0, $a0, %pc_lo12(sym) +// +// Note: Althouth the optimization has been performed, the GOT entries still +// exists, similarly to AArch64. Eliminating the entries will increase code +// complexity. +bool LoongArch::tryGotToPCRel(uint8_t *loc, const Relocation &rHi20, + const Relocation &rLo12, uint64_t secAddr) const { + // Check if the relocations apply to consecutive instructions. + if (rHi20.offset + 4 != rLo12.offset) + return false; + + // Check if the relocations reference the same symbol and skip undefined, + // preemptible and STT_GNU_IFUNC symbols. + if (!rHi20.sym || rHi20.sym != rLo12.sym || !rHi20.sym->isDefined() || + rHi20.sym->isPreemptible || rHi20.sym->isGnuIFunc()) + return false; + + // GOT references to absolute symbols can't be relaxed to use PCALAU12I/ADDI + // in position-independent code because these instructions produce a relative + // address. + if ((ctx.arg.isPic && !cast(*rHi20.sym).section)) + return false; + + // Check if the addends of the both relocations are zero. + if (rHi20.addend != 0 || rLo12.addend != 0) + return false; + + const uint32_t currInsn = read32le(loc); + const uint32_t nextInsn = read32le(loc + 4); + const uint32_t ldOpcode = ctx.arg.is64 ? LD_D : LD_W; + // Check if the first instruction is PCALAU12I and the second instruction is + // LD. + if ((currInsn & 0xfe000000) != PCALAU12I || + (nextInsn & 0xffc00000) != ldOpcode) + return false; + + // Check if use the same register. + if (getD5(currInsn) != getJ5(nextInsn) || getJ5(nextInsn) != getD5(nextInsn)) + return false; + + Symbol &sym = *rHi20.sym; + uint64_t symLocal = sym.getVA(ctx); + const int64_t displace = symLocal - getLoongArchPage(secAddr + rHi20.offset); + // Check if the symbol address is in + // [(PC & ~0xfff) - 2GiB - 0x800, (PC & ~0xfff) + 2GiB - 0x800). + const int64_t underflow = -0x80000000LL - 0x800; + const int64_t overflow = 0x80000000LL - 0x800; + if (!(displace >= underflow && displace < overflow)) + return false; + + Relocation newRHi20 = {RE_LOONGARCH_PAGE_PC, R_LARCH_PCALA_HI20, rHi20.offset, + rHi20.addend, &sym}; + Relocation newRLo12 = {R_ABS, R_LARCH_PCALA_LO12, rLo12.offset, rLo12.addend, + &sym}; + uint64_t pageDelta = + getLoongArchPageDelta(symLocal, secAddr + rHi20.offset, rHi20.type); + // pcalau12i $a0, %pc_hi20 + write32le(loc, insn(PCALAU12I, getD5(currInsn), 0, 0)); + relocate(loc, newRHi20, pageDelta); + // addi.w/d $a0, $a0, %pc_lo12 + write32le(loc + 4, insn(ctx.arg.is64 ? ADDI_D : ADDI_W, getD5(nextInsn), + getJ5(nextInsn), 0)); + relocate(loc + 4, newRLo12, SignExtend64(symLocal, 64)); + return true; +} + // During TLSDESC GD_TO_IE, the converted code sequence always includes an // instruction related to the Lo12 relocation (ld.[wd]). To obtain correct val // in `getRelocTargetVA`, expr of this instruction should be adjusted to @@ -1152,6 +1246,30 @@ RelExpr LoongArch::adjustTlsExpr(RelType type, RelExpr expr) const { return expr; } +static bool pairForGotRels(ArrayRef relocs) { + // Check if R_LARCH_GOT_PC_HI20 and R_LARCH_GOT_PC_LO12 always appear in + // pairs. + size_t i = 0; + const size_t size = relocs.size(); + for (; i != size; ++i) { + if (relocs[i].type == R_LARCH_GOT_PC_HI20) { + if (i + 1 < size && relocs[i + 1].type == R_LARCH_GOT_PC_LO12) { + ++i; + continue; + } + if (relaxable(relocs, i) && i + 2 < size && + relocs[i + 2].type == R_LARCH_GOT_PC_LO12) { + i += 2; + continue; + } + break; + } else if (relocs[i].type == R_LARCH_GOT_PC_LO12) { + break; + } + } + return i == size; +} + void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { const unsigned bits = ctx.arg.is64 ? 64 : 32; uint64_t secAddr = sec.getOutputSection()->addr; @@ -1161,6 +1279,7 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { secAddr += ehIn->getParent()->outSecOff; bool isExtreme = false, isRelax = false; const MutableArrayRef relocs = sec.relocs(); + const bool isPairForGotRels = pairForGotRels(relocs); for (size_t i = 0, size = relocs.size(); i != size; ++i) { Relocation &rel = relocs[i]; uint8_t *loc = buf + rel.offset; @@ -1216,6 +1335,10 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { bits); relocateNoSym(loc, rel.type, val); } else { + isRelax = relaxable(relocs, i); + if (isRelax && (rel.type == R_LARCH_TLS_DESC_PC_HI20 || + rel.type == R_LARCH_TLS_DESC_PC_LO12)) + continue; tlsdescToIe(loc, rel, val); } continue; @@ -1232,9 +1355,32 @@ void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const { bits); relocateNoSym(loc, rel.type, val); } else { + isRelax = relaxable(relocs, i); + if (isRelax && (rel.type == R_LARCH_TLS_DESC_PC_HI20 || + rel.type == R_LARCH_TLS_DESC_PC_LO12 || + (rel.type == R_LARCH_TLS_DESC_LD && isUInt<12>(val)))) + continue; tlsdescToLe(loc, rel, val); } continue; + case RE_LOONGARCH_GOT_PAGE_PC: + // In LoongArch, we try GOT indirection to PC relative optimization in + // normal or medium code model, whether or not with R_LARCH_RELAX + // relocation. Moreover, if the original code sequence can be relaxed to a + // single instruction `pcaddi`, the first instruction will be removed and + // it will not reach here. + if (isPairForGotRels && rel.type == R_LARCH_GOT_PC_HI20) { + bool isRelax = relaxable(relocs, i); + const Relocation lo12Rel = isRelax ? relocs[i + 2] : relocs[i + 1]; + if (lo12Rel.type == R_LARCH_GOT_PC_LO12 && + tryGotToPCRel(loc, rel, lo12Rel, secAddr)) { + // isRelax: skip relocations R_LARCH_RELAX, R_LARCH_GOT_PC_LO12 + // !isRelax: skip relocation R_LARCH_GOT_PC_LO12 + i += isRelax ? 2 : 1; + continue; + } + } + break; default: break; } diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 71e72e7184b9f..62b54f8217bc3 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/STLExtras.h" #include "llvm/LTO/LTO.h" +#include "llvm/Object/Archive.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" @@ -1753,6 +1754,39 @@ static uint8_t getOsAbi(const Triple &t) { } } +// For DTLTO, bitcode member names must be valid paths to files on disk. +// For thin archives, resolve `memberPath` relative to the archive's location. +// Returns true if adjusted; false otherwise. Non-thin archives are unsupported. +static bool dtltoAdjustMemberPathIfThinArchive(Ctx &ctx, StringRef archivePath, + std::string &memberPath) { + assert(!archivePath.empty()); + + if (ctx.arg.dtltoDistributor.empty()) + return false; + + // Read the archive header to determine if it's a thin archive. + auto bufferOrErr = + MemoryBuffer::getFileSlice(archivePath, sizeof(ThinArchiveMagic) - 1, 0); + if (std::error_code ec = bufferOrErr.getError()) { + ErrAlways(ctx) << "cannot open " << archivePath << ": " << ec.message(); + return false; + } + + if (!bufferOrErr->get()->getBuffer().starts_with(ThinArchiveMagic)) + return false; + + SmallString<128> resolvedPath; + if (path::is_relative(memberPath)) { + resolvedPath = path::parent_path(archivePath); + path::append(resolvedPath, memberPath); + } else + resolvedPath = memberPath; + + path::remove_dots(resolvedPath, /*remove_dot_dot=*/true); + memberPath = resolvedPath.str(); + return true; +} + BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName, uint64_t offsetInArchive, bool lazy) : InputFile(ctx, BitcodeKind, mb) { @@ -1763,17 +1797,22 @@ BitcodeFile::BitcodeFile(Ctx &ctx, MemoryBufferRef mb, StringRef archiveName, if (ctx.arg.thinLTOIndexOnly) path = replaceThinLTOSuffix(ctx, mb.getBufferIdentifier()); - // ThinLTO assumes that all MemoryBufferRefs given to it have a unique - // name. If two archives define two members with the same name, this - // causes a collision which result in only one of the objects being taken - // into consideration at LTO time (which very likely causes undefined - // symbols later in the link stage). So we append file offset to make - // filename unique. StringSaver &ss = ctx.saver; - StringRef name = archiveName.empty() - ? ss.save(path) - : ss.save(archiveName + "(" + path::filename(path) + - " at " + utostr(offsetInArchive) + ")"); + StringRef name; + if (archiveName.empty() || + dtltoAdjustMemberPathIfThinArchive(ctx, archiveName, path)) { + name = ss.save(path); + } else { + // ThinLTO assumes that all MemoryBufferRefs given to it have a unique + // name. If two archives define two members with the same name, this + // causes a collision which result in only one of the objects being taken + // into consideration at LTO time (which very likely causes undefined + // symbols later in the link stage). So we append file offset to make + // filename unique. + name = ss.save(archiveName + "(" + path::filename(path) + " at " + + utostr(offsetInArchive) + ")"); + } + MemoryBufferRef mbref(mb.getBuffer(), name); obj = CHECK2(lto::InputFile::create(mbref), this); diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index a5d08f4979dab..b55c19933a13b 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1021,10 +1021,6 @@ void LinkerScript::addOrphanSections() { } }; - // For further --emit-reloc handling code we need target output section - // to be created before we create relocation output section, so we want - // to create target sections first. We do not want priority handling - // for synthetic sections because them are special. size_t n = 0; for (InputSectionBase *isec : ctx.inputSections) { // Process InputSection and MergeInputSection. @@ -1037,10 +1033,18 @@ void LinkerScript::addOrphanSections() { if (ctx.arg.relocatable && (isec->flags & SHF_LINK_ORDER)) continue; - if (auto *sec = dyn_cast(isec)) - if (InputSectionBase *rel = sec->getRelocatedSection()) - if (auto *relIS = dyn_cast_or_null(rel->parent)) - add(relIS); + if (auto *sec = dyn_cast(isec)) { + if (InputSectionBase *relocated = sec->getRelocatedSection()) { + // For --emit-relocs and -r, ensure the output section for .text.foo + // is created before the output section for .rela.text.foo. + add(relocated); + // EhInputSection sections are not added to ctx.inputSections. If we see + // .rela.eh_frame, ensure the output section for the synthetic + // EhFrameSection is created first. + if (auto *p = dyn_cast_or_null(relocated->parent)) + add(p); + } + } add(isec); if (ctx.arg.relocatable) for (InputSectionBase *depSec : isec->dependentSections) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index cebd564036b2c..608cdd0d26660 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -2139,19 +2139,45 @@ void ThunkCreator::mergeThunks(ArrayRef outputSections) { }); } -static int64_t getPCBias(Ctx &ctx, RelType type) { - if (ctx.arg.emachine != EM_ARM) - return 0; - switch (type) { - case R_ARM_THM_JUMP19: - case R_ARM_THM_JUMP24: - case R_ARM_THM_CALL: - return 4; - default: - return 8; +constexpr uint32_t HEXAGON_MASK_END_PACKET = 3 << 14; +constexpr uint32_t HEXAGON_END_OF_PACKET = 3 << 14; +constexpr uint32_t HEXAGON_END_OF_DUPLEX = 0 << 14; + +// Return the distance between the packet start and the instruction in the +// relocation. +static int getHexagonPacketOffset(const InputSection &isec, + const Relocation &rel) { + const ArrayRef data = isec.content(); + + // Search back as many as 3 instructions. + for (unsigned i = 0;; i++) { + if (i == 3 || rel.offset < (i + 1) * 4) + return i * 4; + uint32_t instWord = + read32(isec.getCtx(), data.data() + (rel.offset - (i + 1) * 4)); + if (((instWord & HEXAGON_MASK_END_PACKET) == HEXAGON_END_OF_PACKET) || + ((instWord & HEXAGON_MASK_END_PACKET) == HEXAGON_END_OF_DUPLEX)) + return i * 4; } } +static int64_t getPCBias(Ctx &ctx, const InputSection &isec, + const Relocation &rel) { + if (ctx.arg.emachine == EM_ARM) { + switch (rel.type) { + case R_ARM_THM_JUMP19: + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + return 4; + default: + return 8; + } + } + if (ctx.arg.emachine == EM_HEXAGON) + return -getHexagonPacketOffset(isec, rel); + return 0; +} + // Find or create a ThunkSection within the InputSectionDescription (ISD) that // is in range of Src. An ISD maps to a range of InputSections described by a // linker script section pattern such as { .text .text.* }. @@ -2161,7 +2187,7 @@ ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *os, const Relocation &rel, uint64_t src) { // See the comment in getThunk for -pcBias below. - const int64_t pcBias = getPCBias(ctx, rel.type); + const int64_t pcBias = getPCBias(ctx, *isec, rel); for (std::pair tp : isd->thunkSections) { ThunkSection *ts = tp.first; uint64_t tsBase = os->addr + ts->outSecOff - pcBias; @@ -2322,7 +2348,7 @@ std::pair ThunkCreator::getThunk(InputSection *isec, // out in the relocation addend. We compensate for the PC bias so that // an Arm and Thumb relocation to the same destination get the same keyAddend, // which is usually 0. - const int64_t pcBias = getPCBias(ctx, rel.type); + const int64_t pcBias = getPCBias(ctx, *isec, rel); const int64_t keyAddend = rel.addend + pcBias; // We use a ((section, offset), addend) pair to find the thunk position if @@ -2481,7 +2507,7 @@ bool ThunkCreator::createThunks(uint32_t pass, // STT_SECTION + non-zero addend, clear the addend after // redirection. if (ctx.arg.emachine != EM_MIPS) - rel.addend = -getPCBias(ctx, rel.type); + rel.addend = -getPCBias(ctx, *isec, rel); } for (auto &p : isd->thunkSections) @@ -2525,7 +2551,8 @@ void elf::hexagonTLSSymbolUpdate(Ctx &ctx) { for (Relocation &rel : isec->relocs()) if (rel.sym->type == llvm::ELF::STT_TLS && rel.expr == R_PLT_PC) { if (needEntry) { - sym->allocateAux(ctx); + if (sym->auxIdx == 0) + sym->allocateAux(ctx); addPltEntry(ctx, *ctx.in.plt, *ctx.in.gotPlt, *ctx.in.relaPlt, ctx.target->pltRel, *sym); needEntry = false; diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index c26ba76bccb7e..65d0f094c43c3 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -415,6 +415,22 @@ class AVRThunk : public Thunk { void addSymbols(ThunkSection &isec) override; }; +// Hexagon CPUs need thunks for R_HEX_B{9,1{3,5},22}_PCREL, +// R_HEX_{,GD_}PLT_B22_PCREL when their destination is out of +// range. +class HexagonThunk : public Thunk { +public: + HexagonThunk(Ctx &ctx, const InputSection &isec, Relocation &rel, + Symbol &dest) + : Thunk(ctx, dest, 0), relOffset(rel.offset) { + alignment = 4; + } + uint32_t relOffset; + uint32_t size() override { return ctx.arg.isPic ? 12 : 8; } + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; +}; + // MIPS LA25 thunk class MipsThunk final : public Thunk { public: @@ -1519,6 +1535,39 @@ bool PPC64LongBranchThunk::isCompatibleWith(const InputSection &isec, return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14; } +// Hexagon Target Thunks +static uint64_t getHexagonThunkDestVA(Ctx &ctx, const Symbol &s, int64_t a) { + uint64_t v = s.isInPlt(ctx) ? s.getPltVA(ctx) : s.getVA(ctx, a); + return SignExtend64<32>(v); +} + +void HexagonThunk::writeTo(uint8_t *buf) { + uint64_t s = getHexagonThunkDestVA(ctx, destination, addend); + uint64_t p = getThunkTargetSym()->getVA(ctx); + + if (ctx.arg.isPic) { + write32(ctx, buf + 0, 0x00004000); // { immext(#0) + ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); + write32(ctx, buf + 4, 0x6a49c00e); // r14 = add(pc,##0) } + ctx.target->relocateNoSym(buf + 4, R_HEX_6_PCREL_X, s - p); + + write32(ctx, buf + 8, 0x528ec000); // { jumpr r14 } + } else { + write32(ctx, buf + 0, 0x00004000); // { immext + ctx.target->relocateNoSym(buf, R_HEX_B32_PCREL_X, s - p); + write32(ctx, buf + 4, 0x5800c000); // jump <> } + ctx.target->relocateNoSym(buf + 4, R_HEX_B22_PCREL_X, s - p); + } +} +void HexagonThunk::addSymbols(ThunkSection &isec) { + Symbol *enclosing = isec.getEnclosingSymbol(relOffset); + StringRef src = enclosing ? enclosing->getName() : isec.name; + + addSymbol( + saver().save("__hexagon_thunk_" + destination.getName() + "_from_" + src), + STT_FUNC, 0, isec); +} + Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a) : ctx(ctx), destination(d), addend(a), offset(0) { destination.thunkAccessed = true; @@ -1692,6 +1741,24 @@ static std::unique_ptr addThunkAVR(Ctx &ctx, RelType type, Symbol &s, } } +static std::unique_ptr addThunkHexagon(Ctx &ctx, + const InputSection &isec, + Relocation &rel, Symbol &s) { + switch (rel.type) { + case R_HEX_B9_PCREL: + case R_HEX_B13_PCREL: + case R_HEX_B15_PCREL: + case R_HEX_B22_PCREL: + case R_HEX_PLT_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL: + return std::make_unique(ctx, isec, rel, s); + default: + Fatal(ctx) << "unrecognized relocation " << rel.type << " to " << &s + << " for hexagon target"; + llvm_unreachable(""); + } +} + static std::unique_ptr addThunkMips(Ctx &ctx, RelType type, Symbol &s) { if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6(ctx)) return std::make_unique(ctx, s); @@ -1761,8 +1828,11 @@ std::unique_ptr elf::addThunk(Ctx &ctx, const InputSection &isec, return addThunkPPC32(ctx, isec, rel, s); case EM_PPC64: return addThunkPPC64(ctx, rel.type, s, a); + case EM_HEXAGON: + return addThunkHexagon(ctx, isec, rel, s); default: - llvm_unreachable("add Thunk only supported for ARM, AVR, Mips and PowerPC"); + llvm_unreachable( + "add Thunk only supported for ARM, AVR, Hexagon, Mips and PowerPC"); } } diff --git a/lld/docs/DTLTO.rst b/lld/docs/DTLTO.rst index 985decf6c7db8..54fcc034d1371 100644 --- a/lld/docs/DTLTO.rst +++ b/lld/docs/DTLTO.rst @@ -7,8 +7,7 @@ during the traditional link step. The implementation is documented here: https://llvm.org/docs/DTLTO.html. -Currently, DTLTO is only supported in ELF LLD. Support will be added to other -LLD flavours in the future. +Currently, DTLTO is only supported in ELF and COFF LLD. ELF LLD ------- @@ -40,3 +39,37 @@ The command-line interface is as follows: Some LLD LTO options (e.g., ``--lto-sample-profile=``) are supported. Currently, other options are silently accepted but do not have the intended effect. Support for such options will be expanded in the future. + +COFF LLD +-------- + +The command-line interface is as follows: + +- ``/thinlto-distributor:`` + Specifies the file to execute as the distributor process. If specified, + ThinLTO backend compilations will be distributed. + +- ``/thinlto-remote-compiler:`` + Specifies the path to the compiler that the distributor process will use for + backend compilations. The compiler invoked must match the version of LLD. + +- ``/thinlto-distributor-arg:`` + Specifies ```` on the command line when invoking the distributor. + Can be specified multiple times. + +- ``/thinlto-remote-compiler-arg:`` + Appends ```` to the remote compiler's command line. + Can be specified multiple times. + + Options that introduce extra input/output files may cause miscompilation if + the distribution system does not automatically handle pushing/fetching them to + remote nodes. In such cases, configure the distributor - possibly using + ``/thinlto-distributor-arg:`` - to manage these dependencies. See the + distributor documentation for details. + +Some LLD LTO options (e.g., ``/lto-sample-profile:``) are supported. +Currently, other options are silently accepted but do not have the intended +effect. Support for such options could be expanded in the future. + +Currently, there is no DTLTO command line interface supplied for ``clang-cl``, +as users are expected to invoke LLD directly. \ No newline at end of file diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 863b201891006..03671c6f3b6f2 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -92,6 +92,9 @@ Breaking changes COFF Improvements ----------------- +* ``/thinlto-distributor`` and ``/thinlto-remote-compiler`` options + added to support Integrated Distributed ThinLTO. + (`#147265 `_) MinGW Improvements ------------------ diff --git a/lld/test/COFF/Inputs/manifest-uac.test b/lld/test/COFF/Inputs/manifest-uac.test new file mode 100644 index 0000000000000..5269339489355 --- /dev/null +++ b/lld/test/COFF/Inputs/manifest-uac.test @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/lld/test/COFF/alternatename-alias.s b/lld/test/COFF/alternatename-alias.s new file mode 100644 index 0000000000000..bd0a861380e94 --- /dev/null +++ b/lld/test/COFF/alternatename-alias.s @@ -0,0 +1,15 @@ +// REQUIRES: x86 + +// Check that a weak alias can be used as an alternate name target. +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %s -o %t.obj +// RUN: lld-link -dll -noentry %t.obj -alternatename:sym=altsym + + .data + .rva sym + + .weak altsym + .set altsym,a + + .globl a +a: + .word 1 diff --git a/lld/test/COFF/alternatename-antidep.s b/lld/test/COFF/alternatename-antidep.s new file mode 100644 index 0000000000000..1188a9b75d481 --- /dev/null +++ b/lld/test/COFF/alternatename-antidep.s @@ -0,0 +1,16 @@ +// REQUIRES: x86 + +// Check that an anti-dependency alias can't be used as an alternate name target. +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %s -o %t.obj +// RUN: not lld-link -dll -noentry %t.obj -alternatename:sym=altsym 2>&1 | FileCheck %s +// CHECK: error: undefined symbol: sym + + .data + .rva sym + + .weak_anti_dep altsym + .set altsym,a + + .globl a +a: + .word 1 diff --git a/lld/test/COFF/alternatename-lib.s b/lld/test/COFF/alternatename-lib.s new file mode 100644 index 0000000000000..206fe6bc23978 --- /dev/null +++ b/lld/test/COFF/alternatename-lib.s @@ -0,0 +1,43 @@ +// REQUIRES: x86 +// RUN: split-file %s %t.dir && cd %t.dir + +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows refab.s -o refab.obj +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows aa.s -o aa.obj +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows b.s -o b.obj +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows antidep.s -o antidep.obj +// RUN: llvm-lib -out:aa.lib aa.obj +// RUN: llvm-lib -out:b.lib b.obj + +// Check that -alternatename with an undefined target does not prevent the symbol from being resolved to a library, +// once another alternate name is resolved and pulls in the source symbol. +// RUN: lld-link -out:out.dll -dll -noentry -machine:amd64 refab.obj aa.lib -alternatename:a=aa -alternatename:b=undef + +// Check that -alternatename with an anti-dependency target does not prevent the symbol from being resolved to a library, +// after another alternate name is resolved and pulls in the source symbol. +// RUN: lld-link -out:out2.dll -dll -noentry -machine:amd64 antidep.obj refab.obj aa.lib -alternatename:a=aa -alternatename:b=u + +#--- refab.s + .data + .rva a + .rva b + +#--- aa.s + .globl aa +aa: + .word 1 + + .section .drectve, "yn" + .ascii "/defaultlib:b.lib" + +#--- b.s + .globl b +b: + .word 2 + +#--- antidep.s + .weak_anti_dep u + .set u,d + + .globl d +d: + .word 3 diff --git a/lld/test/COFF/alternatename-lto.ll b/lld/test/COFF/alternatename-lto.ll new file mode 100644 index 0000000000000..c3666cd3501df --- /dev/null +++ b/lld/test/COFF/alternatename-lto.ll @@ -0,0 +1,25 @@ +; REQUIRES: x86 +; RUN: mkdir -p %t.dir +; RUN: llvm-as -o %t.obj %s +; RUN: lld-link -out:%t.dll -dll -noentry %t.obj -export:test + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-windows-msvc19.33.0" + +$alt = comdat any + +@alt = weak_odr dso_local global i32 0, comdat, align 4 +@ext = external dso_local global i32, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @test() #0 { +entry: + %0 = load i32, ptr @ext, align 4 + ret i32 %0 +} + +attributes #0 = { noinline nounwind optnone uwtable } + +!llvm.linker.options = !{!0} + +!0 = !{!"/alternatename:ext=alt"} diff --git a/lld/test/COFF/arm64-delayimport.yaml b/lld/test/COFF/arm64-delayimport.yaml index abb9f25d5c379..5d26978db8be7 100644 --- a/lld/test/COFF/arm64-delayimport.yaml +++ b/lld/test/COFF/arm64-delayimport.yaml @@ -8,31 +8,35 @@ # DISASM: 140001014: d0000011 adrp x17, 0x140003000 # DISASM: 140001018: 91002231 add x17, x17, #8 # DISASM: 14000101c: 14000001 b 0x140001020 <.text+0x20> -# DISASM: 140001020: a9b37bfd stp x29, x30, [sp, #-208]! +# DISASM: 140001020: a9b27bfd stp x29, x30, [sp, #-224]! # DISASM: 140001024: 910003fd mov x29, sp # DISASM: 140001028: a90107e0 stp x0, x1, [sp, #16] # DISASM: 14000102c: a9020fe2 stp x2, x3, [sp, #32] # DISASM: 140001030: a90317e4 stp x4, x5, [sp, #48] # DISASM: 140001034: a9041fe6 stp x6, x7, [sp, #64] -# DISASM: 140001038: ad0287e0 stp q0, q1, [sp, #80] -# DISASM: 14000103c: ad038fe2 stp q2, q3, [sp, #112] -# DISASM: 140001040: ad0497e4 stp q4, q5, [sp, #144] -# DISASM: 140001044: ad059fe6 stp q6, q7, [sp, #176] -# DISASM: 140001048: aa1103e1 mov x1, x17 -# DISASM: 14000104c: b0000000 adrp x0, 0x140002000 -# DISASM: 140001050: 91000000 add x0, x0, #0 -# DISASM: 140001054: 97ffffeb bl 0x140001000 <.text> -# DISASM: 140001058: aa0003f0 mov x16, x0 -# DISASM: 14000105c: ad459fe6 ldp q6, q7, [sp, #176] -# DISASM: 140001060: ad4497e4 ldp q4, q5, [sp, #144] -# DISASM: 140001064: ad438fe2 ldp q2, q3, [sp, #112] -# DISASM: 140001068: ad4287e0 ldp q0, q1, [sp, #80] -# DISASM: 14000106c: a9441fe6 ldp x6, x7, [sp, #64] -# DISASM: 140001070: a94317e4 ldp x4, x5, [sp, #48] -# DISASM: 140001074: a9420fe2 ldp x2, x3, [sp, #32] -# DISASM: 140001078: a94107e0 ldp x0, x1, [sp, #16] -# DISASM: 14000107c: a8cd7bfd ldp x29, x30, [sp], #208 -# DISASM: 140001080: d61f0200 br x16 +# DISASM: 140001038: f9002be8 str x8, [sp, #80] +# DISASM: 14000103c: ad0307e0 stp q0, q1, [sp, #96] +# DISASM: 140001040: ad040fe2 stp q2, q3, [sp, #128] +# DISASM: 140001044: ad0517e4 stp q4, q5, [sp, #160] +# DISASM: 140001048: ad061fe6 stp q6, q7, [sp, #192] +# DISASM: 14000104c: aa1103e1 mov x1, x17 +# DISASM: 140001050: b0000000 adrp x0, 0x140002000 +# DISASM: 140001054: 91000000 add x0, x0, #0 +# DISASM: 140001058: 90000002 adrp x2, 0x140001000 <.text> +# DISASM: 14000105c: 91000042 add x2, x2, #0 +# DISASM: 140001060: d63f0040 blr x2 +# DISASM: 140001064: aa0003f0 mov x16, x0 +# DISASM: 140001068: ad461fe6 ldp q6, q7, [sp, #192] +# DISASM: 14000106c: ad4517e4 ldp q4, q5, [sp, #160] +# DISASM: 140001070: ad440fe2 ldp q2, q3, [sp, #128] +# DISASM: 140001074: ad4307e0 ldp q0, q1, [sp, #96] +# DISASM: 140001078: f9402be8 ldr x8, [sp, #80] +# DISASM: 14000107c: a9441fe6 ldp x6, x7, [sp, #64] +# DISASM: 140001080: a94317e4 ldp x4, x5, [sp, #48] +# DISASM: 140001084: a9420fe2 ldp x2, x3, [sp, #32] +# DISASM: 140001088: a94107e0 ldp x0, x1, [sp, #16] +# DISASM: 14000108c: a8ce7bfd ldp x29, x30, [sp], #224 +# DISASM: 140001090: d61f0200 br x16 # IMPORTS: Format: COFF-ARM64 # IMPORTS: Arch: aarch64 diff --git a/lld/test/COFF/arm64ec-altnames.s b/lld/test/COFF/arm64ec-altnames.s index b2abb24efe4c3..cca778ab8dc64 100644 --- a/lld/test/COFF/arm64ec-altnames.s +++ b/lld/test/COFF/arm64ec-altnames.s @@ -2,6 +2,7 @@ REQUIRES: aarch64 RUN: split-file %s %t.dir && cd %t.dir RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ext.s -o ext.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows ext-mangled.s -o ext-mangled.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows impl.s -o impl.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows impl-cpp.s -o impl-cpp.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig.obj @@ -49,6 +50,20 @@ RUN: lld-link -machine:arm64ec -dll -noentry -out:out4.dll impl-cpp.obj loadconf RUN: llvm-objdump -d out4.dll | FileCheck --check-prefix=DISASM %s RUN: llvm-readobj --hex-dump=.test out4.dll | FileCheck --check-prefix=TESTSEC %s +# Check that when both mangled and demangled alternate names are used, +# only the one whose target is defined is used (the mangled one in this case). + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out5.dll ext-mangled.obj loadconfig.obj "-alternatename:#func=#altsym" -alternatename:func=altsym +RUN: llvm-objdump -d out5.dll | FileCheck --check-prefix=DISASM %s +RUN: llvm-readobj --hex-dump=.test out5.dll | FileCheck --check-prefix=TESTSEC %s + +# Check that when both mangled and demangled alternate names are used, +# only the one whose target is defined is used (the demangled one in this case). + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out6.dll ext.obj loadconfig.obj "-alternatename:#func=#altsym" -alternatename:func=altsym +RUN: llvm-objdump -d out6.dll | FileCheck --check-prefix=DISASM2 %s +RUN: llvm-readobj --hex-dump=.test out6.dll | FileCheck --check-prefix=TESTSEC2 %s + #--- ext.s .weak_anti_dep func .set func, "#func" @@ -70,6 +85,30 @@ altsym: mov w0, #1 ret +#--- ext-mangled.s + .weak_anti_dep func +.set func, "#func" + .weak_anti_dep "#func" +.set "#func", thunksym + + .section .test, "r" + .rva func + .rva "#func" + + .section .thnk,"xr",discard,thunksym +thunksym: + mov w0, #2 + ret + + .section .text,"xr",discard,"#altsym" + .globl "#altsym" +"#altsym": + mov w0, #1 + ret + + .weak_anti_dep altsym + .set altsym,"#altsym" + #--- impl.s .weak_anti_dep func .set func, "#func" diff --git a/lld/test/COFF/arm64ec-codemap.test b/lld/test/COFF/arm64ec-codemap.test index 050261117be2e..bbc682d19920f 100644 --- a/lld/test/COFF/arm64ec-codemap.test +++ b/lld/test/COFF/arm64ec-codemap.test @@ -7,6 +7,7 @@ RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-func-sym2.s -o arm64e RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec.s -o data-sec.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows data-sec2.s -o data-sec2.obj RUN: llvm-mc -filetype=obj -triple=arm64ec-windows empty-sec.s -o arm64ec-empty-sec.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows entry-thunk.s -o entry-thunk.obj RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-func-sym.s -o x86_64-func-sym.obj RUN: llvm-mc -filetype=obj -triple=x86_64-windows empty-sec.s -o x86_64-empty-sec.obj RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj @@ -162,15 +163,17 @@ RUN: loadconfig-arm64ec.obj -dll -noentry -merge:test=.testdata -merge: RUN: llvm-readobj --coff-load-config testcm.dll | FileCheck -check-prefix=CODEMAPCM %s CODEMAPCM: CodeMap [ -CODEMAPCM-NEXT: 0x4008 - 0x4016 X64 +CODEMAPCM-NEXT: 0x4000 - 0x4016 X64 CODEMAPCM-NEXT: ] RUN: llvm-objdump -d testcm.dll | FileCheck -check-prefix=DISASMCM %s DISASMCM: Disassembly of section .testdat: DISASMCM-EMPTY: DISASMCM-NEXT: 0000000180004000 <.testdat>: -DISASMCM-NEXT: 180004000: 00000001 udf #0x1 -DISASMCM-NEXT: 180004004: 00000000 udf #0x0 +DISASMCM-NEXT: 180004000: 01 00 addl %eax, (%rax) +DISASMCM-NEXT: 180004002: 00 00 addb %al, (%rax) +DISASMCM-NEXT: 180004004: 00 00 addb %al, (%rax) +DISASMCM-NEXT: 180004006: 00 00 addb %al, (%rax) DISASMCM-NEXT: 180004008: b8 03 00 00 00 movl $0x3, %eax DISASMCM-NEXT: 18000400d: c3 retq DISASMCM-NEXT: 18000400e: 00 00 addb %al, (%rax) @@ -207,6 +210,14 @@ DISASMMS-NEXT: 0000000180006000 : DISASMMS-NEXT: 180006000: 528000a0 mov w0, #0x5 // =5 DISASMMS-NEXT: 180006004: d65f03c0 ret +Test the code map that includes an ARM64EC function padded by its entry-thunk offset. + +RUN: lld-link -out:testpad.dll -machine:arm64ec entry-thunk.obj loadconfig-arm64ec.obj -dll -noentry -include:func +RUN: llvm-readobj --coff-load-config testpad.dll | FileCheck -check-prefix=CODEMAPPAD %s +CODEMAPPAD: CodeMap [ +CODEMAPPAD: 0x1000 - 0x1010 ARM64EC +CODEMAPPAD-NEXT: ] + #--- arm64-func-sym.s .text @@ -266,3 +277,22 @@ x86_64_func_sym2: .section .empty1, "xr" .section .empty2, "xr" .section .empty3, "xr" + +#--- entry-thunk.s + .section .text,"xr",discard,func + .globl func + .p2align 2, 0x0 +func: + mov w0, #1 + ret + + .section .wowthk$aa,"xr",discard,thunk + .globl thunk + .p2align 2 +thunk: + ret + + .section .hybmp$x,"yi" + .symidx func + .symidx thunk + .word 1 // entry thunk diff --git a/lld/test/COFF/arm64ec-delayimport.test b/lld/test/COFF/arm64ec-delayimport.test index 1e0bd899ba323..01d4ab89982e3 100644 --- a/lld/test/COFF/arm64ec-delayimport.test +++ b/lld/test/COFF/arm64ec-delayimport.test @@ -51,28 +51,28 @@ DISASM-NEXT: 180002016: 48 8d 05 6b 50 00 00 leaq 0x506b(%rip), %rax DISASM-NEXT: 18000201d: e9 0c 00 00 00 jmp 0x18000202e <.text+0x102e> DISASM-NEXT: 180002022: 48 8d 05 67 50 00 00 leaq 0x5067(%rip), %rax # 0x180007090 DISASM-NEXT: 180002029: e9 00 00 00 00 jmp 0x18000202e <.text+0x102e> -DISASM-NEXT: 18000202e: 51 pushq %rcx -DISASM-NEXT: 18000202f: 52 pushq %rdx -DISASM-NEXT: 180002030: 41 50 pushq %r8 -DISASM-NEXT: 180002032: 41 51 pushq %r9 -DISASM-NEXT: 180002034: 48 83 ec 48 subq $0x48, %rsp -DISASM-NEXT: 180002038: 66 0f 7f 04 24 movdqa %xmm0, (%rsp) -DISASM-NEXT: 18000203d: 66 0f 7f 4c 24 10 movdqa %xmm1, 0x10(%rsp) -DISASM-NEXT: 180002043: 66 0f 7f 54 24 20 movdqa %xmm2, 0x20(%rsp) -DISASM-NEXT: 180002049: 66 0f 7f 5c 24 30 movdqa %xmm3, 0x30(%rsp) -DISASM-NEXT: 18000204f: 48 8b d0 movq %rax, %rdx -DISASM-NEXT: 180002052: 48 8d 0d a7 21 00 00 leaq 0x21a7(%rip), %rcx # 0x180004200 -DISASM-NEXT: 180002059: e8 aa ef ff ff callq 0x180001008 <.text+0x8> -DISASM-NEXT: 18000205e: 66 0f 6f 04 24 movdqa (%rsp), %xmm0 -DISASM-NEXT: 180002063: 66 0f 6f 4c 24 10 movdqa 0x10(%rsp), %xmm1 -DISASM-NEXT: 180002069: 66 0f 6f 54 24 20 movdqa 0x20(%rsp), %xmm2 -DISASM-NEXT: 18000206f: 66 0f 6f 5c 24 30 movdqa 0x30(%rsp), %xmm3 -DISASM-NEXT: 180002075: 48 83 c4 48 addq $0x48, %rsp -DISASM-NEXT: 180002079: 41 59 popq %r9 -DISASM-NEXT: 18000207b: 41 58 popq %r8 -DISASM-NEXT: 18000207d: 5a popq %rdx -DISASM-NEXT: 18000207e: 59 popq %rcx -DISASM-NEXT: 18000207f: ff e0 jmpq *%rax +DISASM-NEXT: 18000202e: 48 89 4c 24 08 movq %rcx, 0x8(%rsp) +DISASM-NEXT: 180002033: 48 89 54 24 10 movq %rdx, 0x10(%rsp) +DISASM-NEXT: 180002038: 4c 89 44 24 18 movq %r8, 0x18(%rsp) +DISASM-NEXT: 18000203d: 4c 89 4c 24 20 movq %r9, 0x20(%rsp) +DISASM-NEXT: 180002042: 48 83 ec 68 subq $0x68, %rsp +DISASM-NEXT: 180002046: 66 0f 7f 44 24 20 movdqa %xmm0, 0x20(%rsp) +DISASM-NEXT: 18000204c: 66 0f 7f 4c 24 30 movdqa %xmm1, 0x30(%rsp) +DISASM-NEXT: 180002052: 66 0f 7f 54 24 40 movdqa %xmm2, 0x40(%rsp) +DISASM-NEXT: 180002058: 66 0f 7f 5c 24 50 movdqa %xmm3, 0x50(%rsp) +DISASM-NEXT: 18000205e: 48 8b d0 movq %rax, %rdx +DISASM-NEXT: 180002061: 48 8d 0d 90 21 00 00 leaq 0x2190(%rip), %rcx # 0x1800041f8 +DISASM-NEXT: 180002068: e8 9b ef ff ff callq 0x180001008 <.text+0x8> +DISASM-NEXT: 18000206d: 66 0f 6f 44 24 20 movdqa 0x20(%rsp), %xmm0 +DISASM-NEXT: 180002073: 66 0f 6f 4c 24 30 movdqa 0x30(%rsp), %xmm1 +DISASM-NEXT: 180002079: 66 0f 6f 54 24 40 movdqa 0x40(%rsp), %xmm2 +DISASM-NEXT: 18000207f: 66 0f 6f 5c 24 50 movdqa 0x50(%rsp), %xmm3 +DISASM-NEXT: 180002085: 48 8b 4c 24 70 movq 0x70(%rsp), %rcx +DISASM-NEXT: 18000208a: 48 8b 54 24 78 movq 0x78(%rsp), %rdx +DISASM-NEXT: 18000208f: 4c 8b 84 24 80 00 00 00 movq 0x80(%rsp), %r8 +DISASM-NEXT: 180002097: 4c 8b 8c 24 88 00 00 00 movq 0x88(%rsp), %r9 +DISASM-NEXT: 18000209f: 48 83 c4 68 addq $0x68, %rsp +DISASM-NEXT: 1800020a3: ff e0 jmpq *%rax RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s LOADCFG: CHPEMetadata [ @@ -85,7 +85,7 @@ IMPORTS-NEXT: Name: test.dll IMPORTS-NEXT: Attributes: 0x1 IMPORTS-NEXT: ModuleHandle: 0x7080 IMPORTS-NEXT: ImportAddressTable: 0x7088 -IMPORTS-NEXT: ImportNameTable: 0x4240 +IMPORTS-NEXT: ImportNameTable: 0x4238 IMPORTS-NEXT: BoundDelayImportTable: 0x0 IMPORTS-NEXT: UnloadDelayImportTable: 0x0 IMPORTS-NEXT: Import { @@ -141,7 +141,7 @@ RELOC-NEXT: Address: 0x6008 RELOC-NEXT: } RUN: llvm-readobj --hex-dump=.pdata out.dll | FileCheck --check-prefix=PDATA %s -PDATA: 0x180008000 2e200000 81200000 18400000 +PDATA: 0x180008000 2e200000 a5200000 18400000 Verify that a demangled version of __delayLoadHelper2 can be used. diff --git a/lld/test/COFF/arm64x-delayimport.test b/lld/test/COFF/arm64x-delayimport.test index 56923ef748d09..e705fb0efc455 100644 --- a/lld/test/COFF/arm64x-delayimport.test +++ b/lld/test/COFF/arm64x-delayimport.test @@ -21,7 +21,7 @@ IMPORTS-NEXT: Name: test.dll IMPORTS-NEXT: Attributes: 0x1 IMPORTS-NEXT: ModuleHandle: 0x6080 IMPORTS-NEXT: ImportAddressTable: 0x6088 -IMPORTS-NEXT: ImportNameTable: 0x4390 +IMPORTS-NEXT: ImportNameTable: 0x4388 IMPORTS-NEXT: BoundDelayImportTable: 0x0 IMPORTS-NEXT: UnloadDelayImportTable: 0x0 IMPORTS-NEXT: Import { @@ -35,7 +35,7 @@ IMPORTS-NEXT: Name: test.dll IMPORTS-NEXT: Attributes: 0x1 IMPORTS-NEXT: ModuleHandle: 0x6080 IMPORTS-NEXT: ImportAddressTable: 0x6098 -IMPORTS-NEXT: ImportNameTable: 0x43A0 +IMPORTS-NEXT: ImportNameTable: 0x4398 IMPORTS-NEXT: BoundDelayImportTable: 0x0 IMPORTS-NEXT: UnloadDelayImportTable: 0x0 IMPORTS-NEXT: Import { @@ -61,31 +61,35 @@ DISASM-NEXT: 180001010: d61f0200 br x16 DISASM-NEXT: 180001014: b0000031 adrp x17, 0x180006000 DISASM-NEXT: 180001018: 91022231 add x17, x17, #0x88 DISASM-NEXT: 18000101c: 14000001 b 0x180001020 <.text+0x20> -DISASM-NEXT: 180001020: a9b37bfd stp x29, x30, [sp, #-0xd0]! +DISASM-NEXT: 180001020: a9b27bfd stp x29, x30, [sp, #-0xe0]! DISASM-NEXT: 180001024: 910003fd mov x29, sp DISASM-NEXT: 180001028: a90107e0 stp x0, x1, [sp, #0x10] DISASM-NEXT: 18000102c: a9020fe2 stp x2, x3, [sp, #0x20] DISASM-NEXT: 180001030: a90317e4 stp x4, x5, [sp, #0x30] DISASM-NEXT: 180001034: a9041fe6 stp x6, x7, [sp, #0x40] -DISASM-NEXT: 180001038: ad0287e0 stp q0, q1, [sp, #0x50] -DISASM-NEXT: 18000103c: ad038fe2 stp q2, q3, [sp, #0x70] -DISASM-NEXT: 180001040: ad0497e4 stp q4, q5, [sp, #0x90] -DISASM-NEXT: 180001044: ad059fe6 stp q6, q7, [sp, #0xb0] -DISASM-NEXT: 180001048: aa1103e1 mov x1, x17 -DISASM-NEXT: 18000104c: f0000000 adrp x0, 0x180004000 -DISASM-NEXT: 180001050: 910d4000 add x0, x0, #0x350 -DISASM-NEXT: 180001054: 97ffffeb bl 0x180001000 <.text> -DISASM-NEXT: 180001058: aa0003f0 mov x16, x0 -DISASM-NEXT: 18000105c: ad459fe6 ldp q6, q7, [sp, #0xb0] -DISASM-NEXT: 180001060: ad4497e4 ldp q4, q5, [sp, #0x90] -DISASM-NEXT: 180001064: ad438fe2 ldp q2, q3, [sp, #0x70] -DISASM-NEXT: 180001068: ad4287e0 ldp q0, q1, [sp, #0x50] -DISASM-NEXT: 18000106c: a9441fe6 ldp x6, x7, [sp, #0x40] -DISASM-NEXT: 180001070: a94317e4 ldp x4, x5, [sp, #0x30] -DISASM-NEXT: 180001074: a9420fe2 ldp x2, x3, [sp, #0x20] -DISASM-NEXT: 180001078: a94107e0 ldp x0, x1, [sp, #0x10] -DISASM-NEXT: 18000107c: a8cd7bfd ldp x29, x30, [sp], #0xd0 -DISASM-NEXT: 180001080: d61f0200 br x16 +DISASM-NEXT: 180001038: f9002be8 str x8, [sp, #0x50] +DISASM-NEXT: 18000103c: ad0307e0 stp q0, q1, [sp, #0x60] +DISASM-NEXT: 180001040: ad040fe2 stp q2, q3, [sp, #0x80] +DISASM-NEXT: 180001044: ad0517e4 stp q4, q5, [sp, #0xa0] +DISASM-NEXT: 180001048: ad061fe6 stp q6, q7, [sp, #0xc0] +DISASM-NEXT: 18000104c: aa1103e1 mov x1, x17 +DISASM-NEXT: 180001050: f0000000 adrp x0, 0x180004000 +DISASM-NEXT: 180001054: 910d2000 add x0, x0, #0x348 +DISASM-NEXT: 180001058: 90000002 adrp x2, 0x180001000 <.text> +DISASM-NEXT: 18000105c: 91000042 add x2, x2, #0x0 +DISASM-NEXT: 180001060: d63f0040 blr x2 +DISASM-NEXT: 180001064: aa0003f0 mov x16, x0 +DISASM-NEXT: 180001068: ad461fe6 ldp q6, q7, [sp, #0xc0] +DISASM-NEXT: 18000106c: ad4517e4 ldp q4, q5, [sp, #0xa0] +DISASM-NEXT: 180001070: ad440fe2 ldp q2, q3, [sp, #0x80] +DISASM-NEXT: 180001074: ad4307e0 ldp q0, q1, [sp, #0x60] +DISASM-NEXT: 180001078: f9402be8 ldr x8, [sp, #0x50] +DISASM-NEXT: 18000107c: a9441fe6 ldp x6, x7, [sp, #0x40] +DISASM-NEXT: 180001080: a94317e4 ldp x4, x5, [sp, #0x30] +DISASM-NEXT: 180001084: a9420fe2 ldp x2, x3, [sp, #0x20] +DISASM-NEXT: 180001088: a94107e0 ldp x0, x1, [sp, #0x10] +DISASM-NEXT: 18000108c: a8ce7bfd ldp x29, x30, [sp], #0xe0 +DISASM-NEXT: 180001090: d61f0200 br x16 DISASM-NEXT: ... DISASM-NEXT: 180002000: 52800040 mov w0, #0x2 // =2 DISASM-NEXT: 180002004: d65f03c0 ret @@ -105,28 +109,28 @@ DISASM-NEXT: ... DISASM-NEXT: 180003000: ff 25 92 30 00 00 jmpq *0x3092(%rip) # 0x180006098 DISASM-NEXT: 180003006: 48 8d 05 8b 30 00 00 leaq 0x308b(%rip), %rax # 0x180006098 DISASM-NEXT: 18000300d: e9 00 00 00 00 jmp 0x180003012 <.text+0x2012> -DISASM-NEXT: 180003012: 51 pushq %rcx -DISASM-NEXT: 180003013: 52 pushq %rdx -DISASM-NEXT: 180003014: 41 50 pushq %r8 -DISASM-NEXT: 180003016: 41 51 pushq %r9 -DISASM-NEXT: 180003018: 48 83 ec 48 subq $0x48, %rsp -DISASM-NEXT: 18000301c: 66 0f 7f 04 24 movdqa %xmm0, (%rsp) -DISASM-NEXT: 180003021: 66 0f 7f 4c 24 10 movdqa %xmm1, 0x10(%rsp) -DISASM-NEXT: 180003027: 66 0f 7f 54 24 20 movdqa %xmm2, 0x20(%rsp) -DISASM-NEXT: 18000302d: 66 0f 7f 5c 24 30 movdqa %xmm3, 0x30(%rsp) -DISASM-NEXT: 180003033: 48 8b d0 movq %rax, %rdx -DISASM-NEXT: 180003036: 48 8d 0d 13 13 00 00 leaq 0x1313(%rip), %rcx # 0x180004350 -DISASM-NEXT: 18000303d: e8 c6 ef ff ff callq 0x180002008 <.text+0x1008> -DISASM-NEXT: 180003042: 66 0f 6f 04 24 movdqa (%rsp), %xmm0 -DISASM-NEXT: 180003047: 66 0f 6f 4c 24 10 movdqa 0x10(%rsp), %xmm1 -DISASM-NEXT: 18000304d: 66 0f 6f 54 24 20 movdqa 0x20(%rsp), %xmm2 -DISASM-NEXT: 180003053: 66 0f 6f 5c 24 30 movdqa 0x30(%rsp), %xmm3 -DISASM-NEXT: 180003059: 48 83 c4 48 addq $0x48, %rsp -DISASM-NEXT: 18000305d: 41 59 popq %r9 -DISASM-NEXT: 18000305f: 41 58 popq %r8 -DISASM-NEXT: 180003061: 5a popq %rdx -DISASM-NEXT: 180003062: 59 popq %rcx -DISASM-NEXT: 180003063: ff e0 jmpq *%rax +DISASM-NEXT: 180003012: 48 89 4c 24 08 movq %rcx, 0x8(%rsp) +DISASM-NEXT: 180003017: 48 89 54 24 10 movq %rdx, 0x10(%rsp) +DISASM-NEXT: 18000301c: 4c 89 44 24 18 movq %r8, 0x18(%rsp) +DISASM-NEXT: 180003021: 4c 89 4c 24 20 movq %r9, 0x20(%rsp) +DISASM-NEXT: 180003026: 48 83 ec 68 subq $0x68, %rsp +DISASM-NEXT: 18000302a: 66 0f 7f 44 24 20 movdqa %xmm0, 0x20(%rsp) +DISASM-NEXT: 180003030: 66 0f 7f 4c 24 30 movdqa %xmm1, 0x30(%rsp) +DISASM-NEXT: 180003036: 66 0f 7f 54 24 40 movdqa %xmm2, 0x40(%rsp) +DISASM-NEXT: 18000303c: 66 0f 7f 5c 24 50 movdqa %xmm3, 0x50(%rsp) +DISASM-NEXT: 180003042: 48 8b d0 movq %rax, %rdx +DISASM-NEXT: 180003045: 48 8d 0d fc 12 00 00 leaq 0x12fc(%rip), %rcx # 0x180004348 +DISASM-NEXT: 18000304c: e8 b7 ef ff ff callq 0x180002008 <.text+0x1008> +DISASM-NEXT: 180003051: 66 0f 6f 44 24 20 movdqa 0x20(%rsp), %xmm0 +DISASM-NEXT: 180003057: 66 0f 6f 4c 24 30 movdqa 0x30(%rsp), %xmm1 +DISASM-NEXT: 18000305d: 66 0f 6f 54 24 40 movdqa 0x40(%rsp), %xmm2 +DISASM-NEXT: 180003063: 66 0f 6f 5c 24 50 movdqa 0x50(%rsp), %xmm3 +DISASM-NEXT: 180003069: 48 8b 4c 24 70 movq 0x70(%rsp), %rcx +DISASM-NEXT: 18000306e: 48 8b 54 24 78 movq 0x78(%rsp), %rdx +DISASM-NEXT: 180003073: 4c 8b 84 24 80 00 00 00 movq 0x80(%rsp), %r8 +DISASM-NEXT: 18000307b: 4c 8b 8c 24 88 00 00 00 movq 0x88(%rsp), %r9 +DISASM-NEXT: 180003083: 48 83 c4 68 addq $0x68, %rsp +DISASM-NEXT: 180003087: ff e0 jmpq *%rax RUN: llvm-readobj --coff-load-config out.dll | FileCheck --check-prefix=LOADCFG %s LOADCFG: AuxiliaryDelayloadIAT: 0x5000 @@ -184,31 +188,35 @@ NATIVE-DISASM-NEXT: 180001010: d61f0200 br x16 NATIVE-DISASM-NEXT: 180001014: 90000031 adrp x17, 0x180005000 NATIVE-DISASM-NEXT: 180001018: 91022231 add x17, x17, #0x88 NATIVE-DISASM-NEXT: 18000101c: 14000001 b 0x180001020 <.text+0x20> -NATIVE-DISASM-NEXT: 180001020: a9b37bfd stp x29, x30, [sp, #-0xd0]! +NATIVE-DISASM-NEXT: 180001020: a9b27bfd stp x29, x30, [sp, #-0xe0]! NATIVE-DISASM-NEXT: 180001024: 910003fd mov x29, sp NATIVE-DISASM-NEXT: 180001028: a90107e0 stp x0, x1, [sp, #0x10] NATIVE-DISASM-NEXT: 18000102c: a9020fe2 stp x2, x3, [sp, #0x20] NATIVE-DISASM-NEXT: 180001030: a90317e4 stp x4, x5, [sp, #0x30] NATIVE-DISASM-NEXT: 180001034: a9041fe6 stp x6, x7, [sp, #0x40] -NATIVE-DISASM-NEXT: 180001038: ad0287e0 stp q0, q1, [sp, #0x50] -NATIVE-DISASM-NEXT: 18000103c: ad038fe2 stp q2, q3, [sp, #0x70] -NATIVE-DISASM-NEXT: 180001040: ad0497e4 stp q4, q5, [sp, #0x90] -NATIVE-DISASM-NEXT: 180001044: ad059fe6 stp q6, q7, [sp, #0xb0] -NATIVE-DISASM-NEXT: 180001048: aa1103e1 mov x1, x17 -NATIVE-DISASM-NEXT: 18000104c: d0000000 adrp x0, 0x180003000 -NATIVE-DISASM-NEXT: 180001050: 910cc000 add x0, x0, #0x330 -NATIVE-DISASM-NEXT: 180001054: 97ffffeb bl 0x180001000 <.text> -NATIVE-DISASM-NEXT: 180001058: aa0003f0 mov x16, x0 -NATIVE-DISASM-NEXT: 18000105c: ad459fe6 ldp q6, q7, [sp, #0xb0] -NATIVE-DISASM-NEXT: 180001060: ad4497e4 ldp q4, q5, [sp, #0x90] -NATIVE-DISASM-NEXT: 180001064: ad438fe2 ldp q2, q3, [sp, #0x70] -NATIVE-DISASM-NEXT: 180001068: ad4287e0 ldp q0, q1, [sp, #0x50] -NATIVE-DISASM-NEXT: 18000106c: a9441fe6 ldp x6, x7, [sp, #0x40] -NATIVE-DISASM-NEXT: 180001070: a94317e4 ldp x4, x5, [sp, #0x30] -NATIVE-DISASM-NEXT: 180001074: a9420fe2 ldp x2, x3, [sp, #0x20] -NATIVE-DISASM-NEXT: 180001078: a94107e0 ldp x0, x1, [sp, #0x10] -NATIVE-DISASM-NEXT: 18000107c: a8cd7bfd ldp x29, x30, [sp], #0xd0 -NATIVE-DISASM-NEXT: 180001080: d61f0200 br x16 +NATIVE-DISASM-NEXT: 180001038: f9002be8 str x8, [sp, #0x50] +NATIVE-DISASM-NEXT: 18000103c: ad0307e0 stp q0, q1, [sp, #0x60] +NATIVE-DISASM-NEXT: 180001040: ad040fe2 stp q2, q3, [sp, #0x80] +NATIVE-DISASM-NEXT: 180001044: ad0517e4 stp q4, q5, [sp, #0xa0] +NATIVE-DISASM-NEXT: 180001048: ad061fe6 stp q6, q7, [sp, #0xc0] +NATIVE-DISASM-NEXT: 18000104c: aa1103e1 mov x1, x17 +NATIVE-DISASM-NEXT: 180001050: d0000000 adrp x0, 0x180003000 +NATIVE-DISASM-NEXT: 180001054: 910cc000 add x0, x0, #0x330 +NATIVE-DISASM-NEXT: 180001058: 90000002 adrp x2, 0x180001000 <.text> +NATIVE-DISASM-NEXT: 18000105c: 91000042 add x2, x2, #0x0 +NATIVE-DISASM-NEXT: 180001060: d63f0040 blr x2 +NATIVE-DISASM-NEXT: 180001064: aa0003f0 mov x16, x0 +NATIVE-DISASM-NEXT: 180001068: ad461fe6 ldp q6, q7, [sp, #0xc0] +NATIVE-DISASM-NEXT: 18000106c: ad4517e4 ldp q4, q5, [sp, #0xa0] +NATIVE-DISASM-NEXT: 180001070: ad440fe2 ldp q2, q3, [sp, #0x80] +NATIVE-DISASM-NEXT: 180001074: ad4307e0 ldp q0, q1, [sp, #0x60] +NATIVE-DISASM-NEXT: 180001078: f9402be8 ldr x8, [sp, #0x50] +NATIVE-DISASM-NEXT: 18000107c: a9441fe6 ldp x6, x7, [sp, #0x40] +NATIVE-DISASM-NEXT: 180001080: a94317e4 ldp x4, x5, [sp, #0x30] +NATIVE-DISASM-NEXT: 180001084: a9420fe2 ldp x2, x3, [sp, #0x20] +NATIVE-DISASM-NEXT: 180001088: a94107e0 ldp x0, x1, [sp, #0x10] +NATIVE-DISASM-NEXT: 18000108c: a8ce7bfd ldp x29, x30, [sp], #0xe0 +NATIVE-DISASM-NEXT: 180001090: d61f0200 br x16 RUN: llvm-readobj --coff-load-config out-native.dll | FileCheck --check-prefix=NATIVE-LOADCFG %s NATIVE-LOADCFG: AuxiliaryDelayloadIAT: 0x4000 @@ -230,7 +238,7 @@ EC-IMPORTS-NEXT: Name: test.dll EC-IMPORTS-NEXT: Attributes: 0x1 EC-IMPORTS-NEXT: ModuleHandle: 0x6080 EC-IMPORTS-NEXT: ImportAddressTable: 0x6088 -EC-IMPORTS-NEXT: ImportNameTable: 0x4388 +EC-IMPORTS-NEXT: ImportNameTable: 0x4380 EC-IMPORTS-NEXT: BoundDelayImportTable: 0x0 EC-IMPORTS-NEXT: UnloadDelayImportTable: 0x0 EC-IMPORTS-NEXT: } @@ -243,7 +251,7 @@ EC-IMPORTS-NEXT: Name: test.dll EC-IMPORTS-NEXT: Attributes: 0x1 EC-IMPORTS-NEXT: ModuleHandle: 0x6080 EC-IMPORTS-NEXT: ImportAddressTable: 0x6090 -EC-IMPORTS-NEXT: ImportNameTable: 0x4390 +EC-IMPORTS-NEXT: ImportNameTable: 0x4388 EC-IMPORTS-NEXT: BoundDelayImportTable: 0x0 EC-IMPORTS-NEXT: UnloadDelayImportTable: 0x0 EC-IMPORTS-NEXT: Import { @@ -279,28 +287,28 @@ EC-DISASM-NEXT: ... EC-DISASM-NEXT: 180003000: ff 25 8a 30 00 00 jmpq *0x308a(%rip) # 0x180006090 EC-DISASM-NEXT: 180003006: 48 8d 05 83 30 00 00 leaq 0x3083(%rip), %rax # 0x180006090 EC-DISASM-NEXT: 18000300d: e9 00 00 00 00 jmp 0x180003012 <.text+0x2012> -EC-DISASM-NEXT: 180003012: 51 pushq %rcx -EC-DISASM-NEXT: 180003013: 52 pushq %rdx -EC-DISASM-NEXT: 180003014: 41 50 pushq %r8 -EC-DISASM-NEXT: 180003016: 41 51 pushq %r9 -EC-DISASM-NEXT: 180003018: 48 83 ec 48 subq $0x48, %rsp -EC-DISASM-NEXT: 18000301c: 66 0f 7f 04 24 movdqa %xmm0, (%rsp) -EC-DISASM-NEXT: 180003021: 66 0f 7f 4c 24 10 movdqa %xmm1, 0x10(%rsp) -EC-DISASM-NEXT: 180003027: 66 0f 7f 54 24 20 movdqa %xmm2, 0x20(%rsp) -EC-DISASM-NEXT: 18000302d: 66 0f 7f 5c 24 30 movdqa %xmm3, 0x30(%rsp) -EC-DISASM-NEXT: 180003033: 48 8b d0 movq %rax, %rdx -EC-DISASM-NEXT: 180003036: 48 8d 0d 0b 13 00 00 leaq 0x130b(%rip), %rcx # 0x180004348 -EC-DISASM-NEXT: 18000303d: e8 c6 ef ff ff callq 0x180002008 <.text+0x1008> -EC-DISASM-NEXT: 180003042: 66 0f 6f 04 24 movdqa (%rsp), %xmm0 -EC-DISASM-NEXT: 180003047: 66 0f 6f 4c 24 10 movdqa 0x10(%rsp), %xmm1 -EC-DISASM-NEXT: 18000304d: 66 0f 6f 54 24 20 movdqa 0x20(%rsp), %xmm2 -EC-DISASM-NEXT: 180003053: 66 0f 6f 5c 24 30 movdqa 0x30(%rsp), %xmm3 -EC-DISASM-NEXT: 180003059: 48 83 c4 48 addq $0x48, %rsp -EC-DISASM-NEXT: 18000305d: 41 59 popq %r9 -EC-DISASM-NEXT: 18000305f: 41 58 popq %r8 -EC-DISASM-NEXT: 180003061: 5a popq %rdx -EC-DISASM-NEXT: 180003062: 59 popq %rcx -EC-DISASM-NEXT: 180003063: ff e0 jmpq *%rax +EC-DISASM-NEXT: 180003012: 48 89 4c 24 08 movq %rcx, 0x8(%rsp) +EC-DISASM-NEXT: 180003017: 48 89 54 24 10 movq %rdx, 0x10(%rsp) +EC-DISASM-NEXT: 18000301c: 4c 89 44 24 18 movq %r8, 0x18(%rsp) +EC-DISASM-NEXT: 180003021: 4c 89 4c 24 20 movq %r9, 0x20(%rsp) +EC-DISASM-NEXT: 180003026: 48 83 ec 68 subq $0x68, %rsp +EC-DISASM-NEXT: 18000302a: 66 0f 7f 44 24 20 movdqa %xmm0, 0x20(%rsp) +EC-DISASM-NEXT: 180003030: 66 0f 7f 4c 24 30 movdqa %xmm1, 0x30(%rsp) +EC-DISASM-NEXT: 180003036: 66 0f 7f 54 24 40 movdqa %xmm2, 0x40(%rsp) +EC-DISASM-NEXT: 18000303c: 66 0f 7f 5c 24 50 movdqa %xmm3, 0x50(%rsp) +EC-DISASM-NEXT: 180003042: 48 8b d0 movq %rax, %rdx +EC-DISASM-NEXT: 180003045: 48 8d 0d f4 12 00 00 leaq 0x12f4(%rip), %rcx # 0x180004340 +EC-DISASM-NEXT: 18000304c: e8 b7 ef ff ff callq 0x180002008 <.text+0x1008> +EC-DISASM-NEXT: 180003051: 66 0f 6f 44 24 20 movdqa 0x20(%rsp), %xmm0 +EC-DISASM-NEXT: 180003057: 66 0f 6f 4c 24 30 movdqa 0x30(%rsp), %xmm1 +EC-DISASM-NEXT: 18000305d: 66 0f 6f 54 24 40 movdqa 0x40(%rsp), %xmm2 +EC-DISASM-NEXT: 180003063: 66 0f 6f 5c 24 50 movdqa 0x50(%rsp), %xmm3 +EC-DISASM-NEXT: 180003069: 48 8b 4c 24 70 movq 0x70(%rsp), %rcx +EC-DISASM-NEXT: 18000306e: 48 8b 54 24 78 movq 0x78(%rsp), %rdx +EC-DISASM-NEXT: 180003073: 4c 8b 84 24 80 00 00 00 movq 0x80(%rsp), %r8 +EC-DISASM-NEXT: 18000307b: 4c 8b 8c 24 88 00 00 00 movq 0x88(%rsp), %r9 +EC-DISASM-NEXT: 180003083: 48 83 c4 68 addq $0x68, %rsp +EC-DISASM-NEXT: 180003087: ff e0 jmpq *%rax RUN: llvm-readobj --coff-load-config out-ec.dll | FileCheck --check-prefix=EC-LOADCFG %s EC-LOADCFG: AuxiliaryDelayloadIAT: 0x5000 diff --git a/lld/test/COFF/delayimports.test b/lld/test/COFF/delayimports.test index f410eef35fd1d..ed074f462c7d2 100644 --- a/lld/test/COFF/delayimports.test +++ b/lld/test/COFF/delayimports.test @@ -10,7 +10,7 @@ IMPORT-NEXT: Name: std64.dll IMPORT-NEXT: Attributes: 0x1 IMPORT-NEXT: ModuleHandle: 0x3018 IMPORT-NEXT: ImportAddressTable: 0x3020 -IMPORT-NEXT: ImportNameTable: 0x2050 +IMPORT-NEXT: ImportNameTable: 0x2048 IMPORT-NEXT: BoundDelayImportTable: 0x0 IMPORT-NEXT: UnloadDelayImportTable: 0x0 IMPORT-NEXT: Import { @@ -44,22 +44,18 @@ BASEREL-NEXT: } UNWIND: UnwindInformation [ UNWIND-NEXT: RuntimeFunction { UNWIND-NEXT: StartAddress: (0x14000108A) -UNWIND-NEXT: EndAddress: (0x1400010DD) +UNWIND-NEXT: EndAddress: (0x140001101) UNWIND-NEXT: UnwindInfoAddress: (0x140002000) UNWIND-NEXT: UnwindInfo { UNWIND-NEXT: Version: 1 UNWIND-NEXT: Flags [ (0x0) UNWIND-NEXT: ] -UNWIND-NEXT: PrologSize: 10 +UNWIND-NEXT: PrologSize: 24 UNWIND-NEXT: FrameRegister: - UNWIND-NEXT: FrameOffset: - -UNWIND-NEXT: UnwindCodeCount: 5 +UNWIND-NEXT: UnwindCodeCount: 1 UNWIND-NEXT: UnwindCodes [ -UNWIND-NEXT: 0x0A: ALLOC_SMALL size=72 -UNWIND-NEXT: 0x06: ALLOC_SMALL size=8 -UNWIND-NEXT: 0x04: ALLOC_SMALL size=8 -UNWIND-NEXT: 0x02: ALLOC_SMALL size=8 -UNWIND-NEXT: 0x01: ALLOC_SMALL size=8 +UNWIND-NEXT: 0x18: ALLOC_SMALL size=104 UNWIND-NEXT: ] UNWIND-NEXT: } UNWIND-NEXT: } diff --git a/lld/test/COFF/delayimporttables.yaml b/lld/test/COFF/delayimporttables.yaml index cf54c0a7140a1..ff6681257c835 100644 --- a/lld/test/COFF/delayimporttables.yaml +++ b/lld/test/COFF/delayimporttables.yaml @@ -15,7 +15,7 @@ # CHECK-NEXT: Attributes: 0x1 # CHECK-NEXT: ModuleHandle: 0x3000 # CHECK-NEXT: ImportAddressTable: 0x3010 -# CHECK-NEXT: ImportNameTable: 0x2070 +# CHECK-NEXT: ImportNameTable: 0x2068 # CHECK-NEXT: BoundDelayImportTable: 0x0 # CHECK-NEXT: UnloadDelayImportTable: 0x0 # CHECK-NEXT: Import { @@ -32,16 +32,16 @@ # CHECK-NEXT: Attributes: 0x1 # CHECK-NEXT: ModuleHandle: 0x3008 # CHECK-NEXT: ImportAddressTable: 0x3028 -# CHECK-NEXT: ImportNameTable: 0x2088 +# CHECK-NEXT: ImportNameTable: 0x2080 # CHECK-NEXT: BoundDelayImportTable: 0x0 # CHECK-NEXT: UnloadDelayImportTable: 0x0 # CHECK-NEXT: Import { # CHECK-NEXT: Symbol: left (0) -# CHECK-NEXT: Address: 0x1400010B8 +# CHECK-NEXT: Address: 0x1400010DC # CHECK-NEXT: } # CHECK-NEXT: Import { # CHECK-NEXT: Symbol: right (0) -# CHECK-NEXT: Address: 0x1400010C4 +# CHECK-NEXT: Address: 0x1400010E8 # CHECK-NEXT: } # CHECK-NEXT: } diff --git a/lld/test/COFF/dtlto/files.test b/lld/test/COFF/dtlto/files.test new file mode 100644 index 0000000000000..4297adac9bbf0 --- /dev/null +++ b/lld/test/COFF/dtlto/files.test @@ -0,0 +1,71 @@ +REQUIRES: x86 + +## Test that the LLD options /lldsavetemps and -thinlto-emit-imports-files +## function correctly with DTLTO we also check that index files +## (-thinlto-emit-index-files) are not emitted with DTLTO. + +RUN: rm -rf %t && split-file %s %t && cd %t + +RUN: sed 's/@t1/@t2/g' t1.ll > t2.ll + +## Generate ThinLTO bitcode files. Note that t3.bc will not be used by the +## linker. +RUN: opt -thinlto-bc t1.ll -o t1.bc +RUN: opt -thinlto-bc t2.ll -o t2.bc +RUN: cp t1.bc t3.bc + +## Generate object files for mock.py to return. +RUN: llc t1.ll --filetype=obj -o t1.obj +RUN: llc t2.ll --filetype=obj -o t2.obj + +## Create response file containing shared ThinLTO linker arguments. +## -start-lib/-end-lib is used to test the special case where unused lazy +## bitcode inputs result in empty index/imports files. +## Note that mock.py does not do any compilation; instead, it simply writes +## the contents of the object files supplied on the command line into the +## output object files in job order. +RUN: echo "/entry:t1 /subsystem:console \ +RUN: t1.bc t2.bc -start-lib t3.bc -end-lib /out:my.exe \ +RUN: -thinlto-distributor:\"%python\" \ +RUN: -thinlto-distributor-arg:\"%llvm_src_root/utils/dtlto/mock.py\" \ +RUN: -thinlto-distributor-arg:t1.obj \ +RUN: -thinlto-distributor-arg:t2.obj \ +RUN: -thinlto-remote-compiler:fake.exe" > l.rsp + +## Check that without extra flags, no index/imports files are produced and +## backend temp files are removed. +RUN: lld-link @l.rsp +RUN: ls | FileCheck %s \ +RUN: --check-prefixes=NOBACKEND,NOOTHERS + +## Check that with /lldsavetemps and -thinlto-emit-imports-files backend +## tempoary files are retained and no index/imports files are produced. +RUN: rm -f *.imports *.thinlto.bc +RUN: lld-link @l.rsp /lldsavetemps -thinlto-emit-imports-files +RUN: ls | sort | FileCheck %s \ +RUN: --check-prefixes=BACKEND,NOOTHERS + +## JSON jobs description, retained with --save-temps. +## Note that DTLTO temporary files include a PID component. +NOBACKEND-NOT: {{^}}my.[[#]].dist-file.json{{$}} +BACKEND: {{^}}my.[[#]].dist-file.json{{$}} + +## Index/imports files for t1.bc. +NOOTHERS-NOT: {{^}}t1.bc.imports{{$}} +NOOTHERS-NOT: {{^}}t1.bc.thinlto.bc{{$}} + +## Index/imports files for t2.bc. +NOOTHERS-NOT: {{^}}t2.bc.imports{{$}} +NOOTHERS-NOT: {{^}}t2.bc.thinlto.bc{{$}} + +## Empty index/imports files for unused t3.bc. +NOOTHERS-NOT: {{^}}t3.bc.imports{{$}} +NOOTHERS-NOT: {{^}}t3.bc.thinlto.bc{{$}} + +#--- t1.ll +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define void @t1() { + ret void +} diff --git a/lld/test/COFF/dtlto/options.test b/lld/test/COFF/dtlto/options.test new file mode 100644 index 0000000000000..023ecd2359101 --- /dev/null +++ b/lld/test/COFF/dtlto/options.test @@ -0,0 +1,56 @@ +REQUIRES: x86 + +## Test that DTLTO-specific options are handled correctly. + +RUN: rm -rf %t && split-file %s %t && cd %t + +RUN: opt -thinlto-bc foo.ll -o foo.obj + +## Not specifying a value for -thinlto-remote-compiler should result in an +## error if -thinlto-distributor is specified. +RUN: not lld-link /entry:foo /subsystem:console foo.obj /out:my.exe \ +RUN: -thinlto-distributor:fake.exe 2>&1 | FileCheck %s --check-prefix=COMPILER +RUN: lld-link /entry:foo /subsystem:console foo.obj /out:my.exe + +## Specifying an empty value for -thinlto-remote-compiler should result in an +## error if -thinlto-distributor is specified. +RUN: not lld-link /entry:foo /subsystem:console foo.obj /out:my.exe \ +RUN: -thinlto-distributor:fake.exe \ +RUN: -thinlto-remote-compiler:"" 2>&1 | FileCheck %s --check-prefix=COMPILER +RUN: lld-link /entry:foo /subsystem:console foo.obj /out:my.exe \ +RUN: -thinlto-remote-compiler:"" + +COMPILER: error: A value must be specified for /thinlto-remote-compiler if /thinlto-distributor is specified. + +## Test that DTLTO options are passed correctly to the distributor and +## remote compiler. +## Note: validate.py does not perform any compilation. Instead, it validates the +## received JSON, pretty-prints the JSON and the supplied arguments, and then +## exits with an error. This allows FileCheck directives to verify the +## distributor inputs. +RUN: not lld-link /entry:foo /subsystem:console foo.obj /out:my.exe \ +RUN: -thinlto-distributor:%python \ +RUN: -thinlto-distributor-arg:%llvm_src_root/utils/dtlto/validate.py \ +RUN: -thinlto-distributor-arg:darg1=10 \ +RUN: -thinlto-distributor-arg:darg2=20 \ +RUN: -thinlto-remote-compiler:my_clang.exe \ +RUN: -thinlto-remote-compiler-arg:carg1=20 \ +RUN: -thinlto-remote-compiler-arg:carg2=30 2>&1 | FileCheck %s + +CHECK: distributor_args=['darg1=10', 'darg2=20'] + +CHECK: "linker_output": "my.exe" + +CHECK: "my_clang.exe" +CHECK: "carg1=20" +CHECK: "carg2=30" + +CHECK: error: DTLTO backend compilation: cannot open native object file: + +#--- foo.ll +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define void @foo() { + ret void +} diff --git a/lld/test/COFF/giats.s b/lld/test/COFF/giats.s index f870429f39d85..c0442107d3ae4 100644 --- a/lld/test/COFF/giats.s +++ b/lld/test/COFF/giats.s @@ -37,14 +37,14 @@ # DELAY-CHECK: ImageBase: 0x140000000 # DELAY-CHECK: LoadConfig [ -# DELAY-CHECK: GuardCFFunctionTable: 0x140002124 +# DELAY-CHECK: GuardCFFunctionTable: 0x14000211C # DELAY-CHECK: GuardCFFunctionCount: 2 # DELAY-CHECK: GuardFlags [ (0x10500) # DELAY-CHECK: CF_FUNCTION_TABLE_PRESENT (0x400) # DELAY-CHECK: CF_INSTRUMENTED (0x100) # DELAY-CHECK: CF_LONGJUMP_TABLE_PRESENT (0x10000) # DELAY-CHECK: ] -# DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x14000212C +# DELAY-CHECK: GuardAddressTakenIatEntryTable: 0x140002124 # DELAY-CHECK: GuardAddressTakenIatEntryCount: 1 # DELAY-CHECK: ] # DELAY-CHECK: GuardFidTable [ diff --git a/lld/test/COFF/imported-dllmain-i386.test b/lld/test/COFF/imported-dllmain-i386.test new file mode 100644 index 0000000000000..f8aa09006999c --- /dev/null +++ b/lld/test/COFF/imported-dllmain-i386.test @@ -0,0 +1,58 @@ +REQUIRES: x86 +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-mc -filetype=obj -triple=i386-windows a.s -o a.obj + +RUN: llvm-mc -filetype=obj -triple=i386-windows b1.s -o b1.obj +RUN: llvm-mc -filetype=obj -triple=i386-windows b2.s -o b2.obj + +### This is the line where our problem occurs. Here, we export the DllMain symbol which shouldn't happen normally. +RUN: lld-link b1.obj b2.obj -out:b.dll -dll -implib:b.lib -entry:DllMain -export:bar -export:DllMain -safeseh:no + +RUN: llvm-mc -filetype=obj -triple=i386-windows c.s -o c.obj +RUN: lld-link -lib c.obj -out:c.lib + +### Later, if b.lib is provided before other libs/objs that export DllMain statically, we previously were using the dllimported DllMain from b.lib, which is wrong. +RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -safeseh:no 2>&1 | FileCheck -check-prefix=WARN %s +RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:importeddllmain -safeseh:no 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s +RUN: llvm-objdump --private-headers -d out.dll | FileCheck -check-prefix=DISASM %s + +WARN: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain] +IGNORED-NOT: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain] + +DISASM: The Import Tables: +DISASM: DLL Name: b.dll +DISASM-NOT: DllMain +DISASM: bar +DISASM: Disassembly of section .text: +DISASM: b0 01 movb $0x1, %al +DISASM-NEXT: c3 retl + +#--- a.s + .text + .globl _foo +_foo: + call *__imp__bar + ret + +#--- b1.s + .text + .globl _bar +_bar: + ret + +#--- b2.s + .intel_syntax noprefix + .text + .globl _DllMain +_DllMain: + xor al, al + ret + +#--- c.s + .intel_syntax noprefix + .text + .globl _DllMain +_DllMain: + mov al, 1 + ret diff --git a/lld/test/COFF/exported-dllmain.test b/lld/test/COFF/imported-dllmain.test similarity index 86% rename from lld/test/COFF/exported-dllmain.test rename to lld/test/COFF/imported-dllmain.test index fcf6ed1005379..fa8579b1b41c5 100644 --- a/lld/test/COFF/exported-dllmain.test +++ b/lld/test/COFF/imported-dllmain.test @@ -14,11 +14,11 @@ RUN: lld-link -lib c.obj -out:c.lib ### Later, if b.lib is provided before other libs/objs that export DllMain statically, we previously were using the dllimported DllMain from b.lib, which is wrong. RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain 2>&1 | FileCheck -check-prefix=WARN %s -RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:exporteddllmain 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s +RUN: lld-link a.obj b.lib c.lib -dll -out:out.dll -entry:DllMain -ignore:importeddllmain 2>&1 | FileCheck -check-prefix=IGNORED --allow-empty %s RUN: llvm-objdump --private-headers -d out.dll | FileCheck -check-prefix=DISASM %s -WARN: lld-link: warning: b.lib: skipping exported DllMain symbol [exporteddllmain] -IGNORED-NOT: lld-link: warning: b.lib: skipping exported DllMain symbol [exporteddllmain] +WARN: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain] +IGNORED-NOT: lld-link: warning: b.lib: skipping imported DllMain symbol [importeddllmain] DISASM: The Import Tables: DISASM: DLL Name: b.dll diff --git a/lld/test/COFF/manifest-uac.test b/lld/test/COFF/manifest-uac.test new file mode 100644 index 0000000000000..d3a17c7282716 --- /dev/null +++ b/lld/test/COFF/manifest-uac.test @@ -0,0 +1,33 @@ +# REQUIRES: libxml2 + +# RUN: yaml2obj %p/Inputs/ret42.yaml -o %t.obj +# RUN: lld-link /out:%t.exe /entry:main \ +# RUN: /manifest:embed \ +# RUN: /manifestinput:%p/Inputs/manifest-uac.test %t.obj +# RUN: llvm-readobj --coff-resources %t.exe | FileCheck %s + +CHECK: Data ( +CHECK-NEXT: 0000: 3C3F786D 6C207665 7273696F 6E3D2231 |.| +CHECK-NEXT: 0070: 0A20203C 74727573 74496E66 6F20786D |. . . . . <| +CHECK-NEXT: 0120: 2F726571 75657374 65645072 6976696C |/requestedPrivil| +CHECK-NEXT: 0130: 65676573 3E0A2020 20203C2F 73656375 |eges>. . .| +CHECK-NEXT: 0160: 0A |.| +CHECK-NEXT: ) diff --git a/lld/test/COFF/manifest.test b/lld/test/COFF/manifest.test index 4910600bd3a17..09de96e9bccfa 100644 --- a/lld/test/COFF/manifest.test +++ b/lld/test/COFF/manifest.test @@ -10,7 +10,7 @@ MANIFEST: MANIFEST: -MANIFEST: +MANIFEST: MANIFEST: MANIFEST: MANIFEST: @@ -26,7 +26,7 @@ MANIFEST: UAC: UAC: -UAC: +UAC: UAC: UAC: UAC: @@ -43,7 +43,7 @@ UAC: DEPENDENCY: DEPENDENCY: -DEPENDENCY: +DEPENDENCY: DEPENDENCY: DEPENDENCY: DEPENDENCY: @@ -90,7 +90,7 @@ NOUACNODEP: SEVERALDEPS: SEVERALDEPS: -SEVERALDEPS: +SEVERALDEPS: SEVERALDEPS: SEVERALDEPS: SEVERALDEPS: @@ -139,31 +139,34 @@ EMBED: 0040: 6D61732D 6D696372 6F736F66 742D636F |mas-microsoft-co| EMBED: 0050: 6D3A6173 6D2E7631 220A2020 20202020 |m:asm.v1". | EMBED: 0060: 20202020 6D616E69 66657374 56657273 | manifestVers| EMBED: 0070: 696F6E3D 22312E30 223E0A20 203C7472 |ion="1.0">. . . . . | -EMBED: 0100: 203C2F72 65717565 73746564 50726976 | . . . . . | -EMBED: 0160: 20202020 3C617373 656D626C 79496465 | . . . . <| -EMBED: 01C0: 64657065 6E64656E 74417373 656D626C |dependentAssembl| -EMBED: 01D0: 793E0A20 20202020 203C6173 73656D62 |y>. . . ..| +EMBED: 0080: 75737449 6E666F20 786D6C6E 733D2275 |ustInfo xmlns="u| +EMBED: 0090: 726E3A73 6368656D 61732D6D 6963726F |rn:schemas-micro| +EMBED: 00A0: 736F6674 2D636F6D 3A61736D 2E763322 |soft-com:asm.v3"| +EMBED: 00B0: 3E0A2020 20203C73 65637572 6974793E |>. | +EMBED: 00C0: 0A202020 2020203C 72657175 65737465 |. . | +EMBED: 00E0: 20202020 20203C72 65717565 73746564 | . | +EMBED: 0140: 0A202020 203C2F73 65637572 6974793E |. | +EMBED: 0150: 0A20203C 2F747275 7374496E 666F3E0A |. .| +EMBED: 0160: 20203C64 6570656E 64656E63 793E0A20 | . | +EMBED: 0170: 2020203C 64657065 6E64656E 74417373 | . . | +EMBED: 01B0: 3C2F6465 70656E64 656E7441 7373656D |. . . . | +EMBED: 0200: 20203C61 7373656D 626C7949 64656E74 | . . ..| EMBED: ) diff --git a/lld/test/COFF/manifestinput.test b/lld/test/COFF/manifestinput.test index 04af80a13312d..cbf27b1ea96b5 100644 --- a/lld/test/COFF/manifestinput.test +++ b/lld/test/COFF/manifestinput.test @@ -5,22 +5,21 @@ # RUN: /manifest:embed \ # RUN: /manifestuac:"level='requireAdministrator'" \ # RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj -# RUN: llvm-readobj --coff-resources --file-headers %t.exe | FileCheck %s \ -# RUN: -check-prefix TEST_EMBED +# RUN: llvm-readobj --coff-resources --file-headers %t.exe | FileCheck %s -TEST_EMBED: ResourceTableRVA: 0x2000 -TEST_EMBED-NEXT: ResourceTableSize: 0x2A0 -TEST_EMBED-DAG: Resources [ -TEST_EMBED-NEXT: Total Number of Resources: 1 -TEST_EMBED-DAG: Number of String Entries: 0 -TEST_EMBED-NEXT: Number of ID Entries: 1 -TEST_EMBED-NEXT: Type: MANIFEST (ID 24) [ -TEST_EMBED-NEXT: Table Offset: 0x18 -TEST_EMBED-NEXT: Number of String Entries: 0 -TEST_EMBED-NEXT: Number of ID Entries: 1 -TEST_EMBED-NEXT: Name: (ID 1) [ -TEST_EMBED-NEXT: Table Offset: 0x30 -TEST_EMBED-NEXT: Number of String Entries: 0 -TEST_EMBED-NEXT: Number of ID Entries: 1 -TEST_EMBED-NEXT: Language: (ID 1033) [ -TEST_EMBED-NEXT: Entry Offset: 0x48 +CHECK: ResourceTableRVA: 0x2000 +CHECK-NEXT: ResourceTableSize: 0x2C8 +CHECK-DAG: Resources [ +CHECK-NEXT: Total Number of Resources: 1 +CHECK-DAG: Number of String Entries: 0 +CHECK-NEXT: Number of ID Entries: 1 +CHECK-NEXT: Type: MANIFEST (ID 24) [ +CHECK-NEXT: Table Offset: 0x18 +CHECK-NEXT: Number of String Entries: 0 +CHECK-NEXT: Number of ID Entries: 1 +CHECK-NEXT: Name: (ID 1) [ +CHECK-NEXT: Table Offset: 0x30 +CHECK-NEXT: Number of String Entries: 0 +CHECK-NEXT: Number of ID Entries: 1 +CHECK-NEXT: Language: (ID 1033) [ +CHECK-NEXT: Entry Offset: 0x48 diff --git a/lld/test/COFF/pdb-empty-sec.s b/lld/test/COFF/pdb-empty-sec.s new file mode 100644 index 0000000000000..0d61447b76651 --- /dev/null +++ b/lld/test/COFF/pdb-empty-sec.s @@ -0,0 +1,19 @@ +// REQUIRES: x86 + +// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %s -o %t.obj +// RUN: lld-link -dll -noentry -debug %t.obj -out:%t.dll +// RUN: llvm-pdbutil dump -publics %t.pdb | FileCheck %s + +// CHECK: Records +// CHECK-NEXT: 0 | S_PUB32 [size = 20] `func` +// CHECK-NEXT: flags = none, addr = 0001:0000 +// CHECK-NEXT: 20 | S_PUB32 [size = 20] `sym` +// CHECK-NEXT: flags = none, addr = 0000:0000 + + .globl sym + .data +sym: + .text + .globl func +func: + ret diff --git a/lld/test/COFF/strtab.s b/lld/test/COFF/strtab.s index fbdd8df52d540..9edc13e19e825 100644 --- a/lld/test/COFF/strtab.s +++ b/lld/test/COFF/strtab.s @@ -1,17 +1,32 @@ # REQUIRES: x86 # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.obj -# RUN: lld-link -out:%t.exe -entry:main %t.obj -debug:dwarf +# RUN: lld-link -machine:x64 -def:%S/Inputs/library.def -implib:%t.lib +# RUN: lld-link -out:%t.exe -entry:main %t.obj %t.lib -debug:dwarf # RUN: llvm-readobj --string-table %t.exe | FileCheck %s +# RUN: llvm-nm %t.exe | FileCheck %s --check-prefix=SYMBOLS + +# Note, for this test to have the intended test coverage, the imported symbol +# "function" needs to be such that the symbol name itself is <= 8 chars, while +# "__imp_"+name is >8 chars. # CHECK: StringTable { -# CHECK-NEXT: Length: 87 +# CHECK-NEXT: Length: 102 # CHECK-NEXT: [ 4] .debug_abbrev # CHECK-NEXT: [ 12] .debug_line # CHECK-NEXT: [ 1e] long_name_symbolz # CHECK-NEXT: [ 30] .debug_abbrez -# CHECK-NEXT: [ 3e] __impl_long_name_symbolA +# CHECK-NEXT: [ 3e] __imp_function +# CHECK-NEXT: [ 4d] __impl_long_name_symbolA # CHECK-NEXT: } +# SYMBOLS: 140001000 N .debug_abbrez +# SYMBOLS-NEXT: 140002070 R __imp_function +# SYMBOLS-NEXT: 140001000 t __impl_long_name_symbolA +# SYMBOLS-NEXT: 140001010 T function +# SYMBOLS-NEXT: 140001000 t long_name_symbolA +# SYMBOLS-NEXT: 140001000 t long_name_symbolz +# SYMBOLS-NEXT: 140001000 T main +# SYMBOLS-NEXT: 140001000 t name_symbolA .global main .text @@ -21,6 +36,7 @@ long_name_symbolA: __impl_long_name_symbolA: name_symbolA: .debug_abbrez: + call function ret .section .debug_abbrev,"dr" diff --git a/lld/test/COFF/thin-archive.s b/lld/test/COFF/thin-archive.s index 55d71ea635673..7fab10c2b57b4 100644 --- a/lld/test/COFF/thin-archive.s +++ b/lld/test/COFF/thin-archive.s @@ -22,23 +22,34 @@ # SYMTAB: ?f@@YAHXZ in # NO-SYMTAB-NOT: ?f@@YAHXZ in -# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \ -# RUN: FileCheck --allow-empty %s -# RUN: lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \ -# RUN: FileCheck --allow-empty %s -# RUN: lld-link /entry:main %t.main.obj /wholearchive:%t_thin.lib /out:%t.exe 2>&1 | \ -# RUN: FileCheck --allow-empty %s +# RUN: echo "/entry:main \"%t.main.obj\" /out:\"%t.exe\"" > %t.rsp + +# RUN: lld-link @%t.rsp %t.lib /verbose 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LOAD_NON_THIN +# RUN: lld-link @%t.rsp %t_thin.lib /verbose 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LOAD_THIN_SYM +# RUN: lld-link @%t.rsp /wholearchive:%t_thin.lib /verbose 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LOAD_THIN_WHOLE +# RUN: lld-link @%t.rsp /wholearchive %t_thin.lib /verbose 2>&1 | \ +# RUN: FileCheck %s --check-prefix=LOAD_THIN_WHOLE + +# LOAD_NON_THIN: Loaded {{.*}}.lib({{.*}}.obj) for int __cdecl f(void) +# LOAD_THIN_SYM: Loaded {{.*}}.obj for int __cdecl f(void) +# LOAD_THIN_WHOLE: Loaded {{.*}}.obj for # RUN: rm %t.lib.obj -# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \ -# RUN: FileCheck --allow-empty %s -# RUN: env LLD_IN_TEST=1 not lld-link /entry:main %t.main.obj %t_thin.lib \ -# RUN: /out:%t.exe 2>&1 | FileCheck --check-prefix=NOOBJ %s -# RUN: env LLD_IN_TEST=1 not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe \ -# RUN: /demangle:no 2>&1 | FileCheck --check-prefix=NOOBJNODEMANGLE %s - -# CHECK-NOT: error: could not get the buffer for the member defining +# RUN: lld-link @%t.rsp %t.lib 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR --allow-empty +# RUN: env LLD_IN_TEST=1 not lld-link @%t.rsp %t_thin.lib 2>&1 | \ +# RUN: FileCheck %s --check-prefix=NOOBJ +# RUN: env LLD_IN_TEST=1 not lld-link @%t.rsp /wholearchive:%t_thin.lib 2>&1 | \ +# RUN: FileCheck %s --check-prefix=NOOBJWHOLE +# RUN: env LLD_IN_TEST=1 not lld-link @%t.rsp %t_thin.lib /demangle:no 2>&1 | \ +# RUN: FileCheck %s --check-prefix=NOOBJNODEMANGLE + +# ERR-NOT: error: could not get the buffer for the member defining # NOOBJ: error: could not get the buffer for the member defining symbol int __cdecl f(void): {{.*}}.lib({{.*}}.lib.obj): +# NOOBJWHOLE: error: {{.*}}.lib: could not get the buffer for a child of the archive: '{{.*}}.obj' # NOOBJNODEMANGLE: error: could not get the buffer for the member defining symbol ?f@@YAHXZ: {{.*}}.lib({{.*}}.lib.obj): .text diff --git a/lld/test/ELF/aarch64-build-attributes.s b/lld/test/ELF/aarch64-build-attributes.s index 24e15f94e3d4a..815aed32f2aaa 100644 --- a/lld/test/ELF/aarch64-build-attributes.s +++ b/lld/test/ELF/aarch64-build-attributes.s @@ -1,4 +1,5 @@ // REQUIRES: aarch64 +// RUN: rm -rf %t %t.o %t.so %t2.o // RUN: llvm-mc -triple=aarch64 %s -filetype=obj -o %t.o // RUN: ld.lld %t.o --shared -o %t.so // RUN: llvm-readelf --sections %t.so | FileCheck %s diff --git a/lld/test/ELF/dtlto/archive-thin.test b/lld/test/ELF/dtlto/archive-thin.test new file mode 100644 index 0000000000000..df3c2aadb06eb --- /dev/null +++ b/lld/test/ELF/dtlto/archive-thin.test @@ -0,0 +1,65 @@ +REQUIRES: x86 + +## Test that a DTLTO link assigns Module IDs to thin archive members as expected. + +RUN: rm -rf %t && split-file %s %t && cd %t + +RUN: sed 's/@t1/@t2/g' t1.ll > t2.ll +RUN: sed 's/@t1/@t3/g' t1.ll > t3.ll + +RUN: opt -thinlto-bc t1.ll -o t1.bc +RUN: opt -thinlto-bc t2.ll -o t2.bc +RUN: opt -thinlto-bc t3.ll -o t3.bc + +RUN: llvm-ar rcs t1.a t1.bc --thin +## Create this bitcode thin archive in a subdirectory to test the expansion of +## the path to a bitcode file that is referenced using "..", e.g., in this case +## "../t2.bc". +RUN: mkdir lib +RUN: llvm-ar rcs lib/t2.a t2.bc --thin +## Create this bitcode thin archive with an absolute path entry containing "..". +RUN: llvm-ar rcs t3.a %t/lib/../t3.bc --thin + +## Link from a different directory to ensure that thin archive member paths are +## resolved correctly relative to the archive locations. +RUN: mkdir %t/out && cd %t/out + +## Build a response file to share common linking arguments. +## Note: validate.py does not perform any compilation. Instead, it validates the +## received JSON, pretty-prints the JSON and the supplied arguments, and then +## exits with an error. This allows FileCheck directives to verify the +## distributor inputs. +RUN: echo "%t/t1.a %t/lib/t2.a ../t3.a \ +RUN: --thinlto-distributor=\"%python\" \ +RUN: --thinlto-distributor-arg=\"%llvm_src_root/utils/dtlto/validate.py\"" > rsp + +## Link thin archives using -u/--undefined. +RUN: not ld.lld @rsp -u t1 -u t2 -u t3 2>&1 | FileCheck %s + +## Link thin archives using --whole-archive. +RUN: not ld.lld --whole-archive @rsp 2>&1 | FileCheck %s + +## Check the module IDs in the JSON jobs description. +CHECK: "jobs": [ +CHECK: "inputs": [ +CHECK-NEXT: "{{([a-zA-Z]:)|/}} +CHECK-SAME: {{/|\\\\}}archive-thin.test.tmp{{/|\\\\}}t1.bc" + +CHECK: "inputs": [ +CHECK-NEXT: "{{([a-zA-Z]\:)|/}} +CHECK-SAME: {{/|\\\\}}archive-thin.test.tmp{{/|\\\\}}t2.bc" + +CHECK: "inputs": [ +CHECK-NEXT: "{{([a-zA-Z]:)|/}} +CHECK-SAME: {{/|\\\\}}archive-thin.test.tmp{{/|\\\\}}t3.bc" + +## Ensure backend compilation fails as expected (due to validate.py dummy behavior). +CHECK: error: DTLTO backend compilation: cannot open native object file: + +#--- t1.ll +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @t1() { + ret void +} diff --git a/lld/test/ELF/hexagon-jump-error.s b/lld/test/ELF/hexagon-jump-error.s deleted file mode 100644 index 53860b5daf2b1..0000000000000 --- a/lld/test/ELF/hexagon-jump-error.s +++ /dev/null @@ -1,32 +0,0 @@ -# REQUIRES: hexagon -# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o -## Use --threads=1 to keep emitted warnings across sections sequential. -# RUN: not ld.lld %t.o -o /dev/null --threads=1 2>&1 | FileCheck --implicit-check-not "out of range" %s - - .globl _start - .type _start, @function -_start: - -# CHECK: relocation R_HEX_B9_PCREL out of range: 1028 is not in [-1024, 1023] -{r0 = #0; jump #1f} -.space (1<<10) -.section b9, "ax" -1: - -# CHECK: relocation R_HEX_B13_PCREL out of range: 16388 is not in [-16384, 16383] -if (r0==#0) jump:t #1f -.space (1<<14) -.section b13, "ax" -1: - -# CHECK: relocation R_HEX_B15_PCREL out of range: 65540 is not in [-65536, 65535] -if (p0) jump #1f -.space (1<<16) -.section b15, "ax" -1: - -# CHECK: relocation R_HEX_B22_PCREL out of range: 8388612 is not in [-8388608, 8388607] -jump #1f -.space (1<<23) -.section b22, "ax" -1: diff --git a/lld/test/ELF/hexagon-plt.s b/lld/test/ELF/hexagon-plt.s index 679de82923a72..780dc434a6698 100644 --- a/lld/test/ELF/hexagon-plt.s +++ b/lld/test/ELF/hexagon-plt.s @@ -30,31 +30,31 @@ # DIS: <_start>: ## Direct call ## Call foo directly -# DIS-NEXT: { call 0x2003c } +# DIS-NEXT: { call 0x2003c } ## Call bar via plt -# DIS-NEXT: { call 0x20060 } +# DIS-NEXT: { call 0x20060 } ## Call weak via plt -# DIS-NEXT: { call 0x20070 } +# DIS-NEXT: { call 0x20070 } # DIS-NEXT: { immext(#0) ## Call foo directly -# DIS-NEXT: if (p0) jump:nt 0x2003c } +# DIS-NEXT: if (p0) jump:nt 0x2003c } # DIS-NEXT: { immext(#64) ## Call bar via plt -# DIS-NEXT: if (p0) jump:nt 0x20060 } +# DIS-NEXT: if (p0) jump:nt 0x20060 } # DIS-NEXT: { immext(#64) ## Call weak via plt -# DIS-NEXT: if (p0) jump:nt 0x20070 } +# DIS-NEXT: if (p0) jump:nt 0x20070 } # DIS-NEXT: { immext(#0) ## Call foo directly -# DIS-NEXT: r0 = #0 ; jump 0x2003c } +# DIS-NEXT: r0 = #0 ; jump 0x2003c } # DIS-NEXT: { immext(#0) ## Call bar via plt -# DIS-NEXT: r0 = #0 ; jump 0x20060 } +# DIS-NEXT: r0 = #0 ; jump 0x20060 } # DIS-NEXT: { immext(#0) ## Call weak via plt -# DIS-NEXT: r0 = #0 ; jump 0x20070 } +# DIS-NEXT: r0 = #0 ; jump 0x20070 } # DIS: : # DIS-NEXT: 2003c: diff --git a/lld/test/ELF/hexagon-shared.s b/lld/test/ELF/hexagon-shared.s index cc62662d278e2..7f7390f1fa8d8 100644 --- a/lld/test/ELF/hexagon-shared.s +++ b/lld/test/ELF/hexagon-shared.s @@ -88,7 +88,7 @@ pvar: # PLT-NEXT: jumpr r28 } # TEXT: bc 00 01 00 000100bc -# TEXT: { call 0x10300 } +# TEXT: { call 0x10300 } # TEXT: if (p0) jump:nt 0x10300 # TEXT: r0 = #0 ; jump 0x10300 # TEXT: r0 = add(r1,##-65548) diff --git a/lld/test/ELF/hexagon-thunk-range-b22rel.s b/lld/test/ELF/hexagon-thunk-range-b22rel.s new file mode 100644 index 0000000000000..08e37bf0a5552 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-b22rel.s @@ -0,0 +1,115 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld main.o -o test +# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_B22_PCREL relocations. +## R_HEX_B22_PCREL has a range of +/- 8MB (0x800000 bytes). + +#--- main.s +.globl _start +.type _start, %function +_start: + call target_within_range_max + call target_beyond_range + call target_within_range_min + call target_beyond_range_min + call target_multiple_calls + call target_multiple_calls + call target_close + jumpr r31 + +target_close: + jumpr r31 + +## Target at maximum positive range (8MB - 4 bytes from _start) +## We need to account for the instructions above: 7 calls + 1 jumpr = 8 * 4 = 32 bytes +.skip 0X7fffbc +.globl target_within_range_max +.type target_within_range_max, %function +target_within_range_max: + jumpr r31 + +## Target just beyond maximum positive range (needs thunk) +.skip 8 +.globl target_beyond_range +.type target_beyond_range, %function +target_beyond_range: + call target_within_range_max + jumpr r31 + +## Target for multiple calls test +.skip 0x100000 +.globl target_multiple_calls +.type target_multiple_calls, %function +target_multiple_calls: + jumpr r31 + +## Now place targets at maximum negative range +## We'll put these before _start in memory layout +.section .text_negative, "ax", %progbits + +## Target at maximum negative range (-8MB + 4 bytes from _start) +.globl target_within_range_min +.type target_within_range_min, %function +target_within_range_min: + call target_close + jumpr r31 + +.skip 0X7ffff4 + +## Target beyond maximum negative range (needs thunk) +.globl target_beyond_range_min +.type target_beyond_range_min, %function +target_beyond_range_min: + jumpr r31 + +## Verify thunk generation for targets beyond B22_PCREL range +# CHECK: <__hexagon_thunk_target_within_range_min_from_.text.thunk>: +# CHECK-NEXT: 200b4: { immext(#0x900000) +# CHECK-NEXT: jump 0x9200cc } + +# CHECK: <__hexagon_thunk_target_beyond_range_min_from_.text.thunk>: +# CHECK-NEXT: 200bc: { immext(#0x1100000) +# CHECK-NEXT: jump 0x11200c8 } + +# CHECK: <__hexagon_thunk_target_multiple_calls_from_.text.thunk>: +# CHECK-NEXT: 200c4: { immext(#0x8fffc0) +# CHECK-NEXT: jump 0x9200c0 } + +## Verify _start calls - some direct, some via thunks +# CHECK: <_start>: +# CHECK-NEXT: 200cc: { call 0x8200ac } +# CHECK-NEXT: { call 0x8200b8 } +# CHECK-NEXT: { call 0x200b4 <__hexagon_thunk_target_within_range_min_from_.text.thunk> } +# CHECK-NEXT: { call 0x200bc <__hexagon_thunk_target_beyond_range_min_from_.text.thunk> } +# CHECK-NEXT: { call 0x200c4 <__hexagon_thunk_target_multiple_calls_from_.text.thunk> } +# CHECK-NEXT: { call 0x200c4 <__hexagon_thunk_target_multiple_calls_from_.text.thunk> } +# CHECK-NEXT: { call 0x200ec } + +# CHECK: : +# CHECK-NEXT: 200ec: { jumpr r31 } + +## Verify targets at maximum positive range (direct calls, no thunks needed) +# CHECK: : +# CHECK-NEXT: 8200ac: { jumpr r31 } + +# CHECK: : +# CHECK-NEXT: 8200b8: { call 0x8200ac } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: : +# CHECK-NEXT: 9200c0: { jumpr r31 } + +## Verify targets in negative section and thunk for calling back to main section +# CHECK: <__hexagon_thunk__from_.text.thunk>: +# CHECK-NEXT: 9200c4: { immext(#0xff700000) +# CHECK-NEXT: jump 0x200cc <_start> } + +# CHECK: : +# CHECK-NEXT: 9200cc: { call 0x9200c4 <__hexagon_thunk__from_.text.thunk> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: : +# CHECK-NEXT: 11200c8: { jumpr r31 } diff --git a/lld/test/ELF/hexagon-thunk-range-gdplt.s b/lld/test/ELF/hexagon-thunk-range-gdplt.s new file mode 100644 index 0000000000000..77fd0e5754568 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-gdplt.s @@ -0,0 +1,95 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld -shared main.o -o test.so +# RUN: llvm-objdump -d --no-show-raw-insn test.so | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_GD_PLT_B22_PCREL relocations. +## Same ±8MB range as regular calls. + +#--- main.s +.globl _start +.type _start, @function +_start: + ## Setup for TLS Global Dynamic calls + r2 = add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) + + ## Test TLS GD PLT calls + r0 = add(r2,##tls_var_close@GDGOT) + call tls_var_close@GDPLT + + r0 = add(r2,##tls_var_far@GDGOT) + call tls_var_far@GDPLT + + jumpr r31 + +.skip 0x400000 + +more_code: + r0 = add(r2,##tls_var_distant@GDGOT) + call tls_var_distant@GDPLT + jumpr r31 + +## TLS variables in .tdata section +.section .tdata,"awT",@progbits +.globl tls_var_close, tls_var_far, tls_var_distant +.type tls_var_close, @object +.type tls_var_far, @object +.type tls_var_distant, @object + +tls_var_close: + .word 0x1234 + +tls_var_far: + .word 0x5678 + +tls_var_distant: + .word 0x9abc + +# CHECK: Disassembly of section .text: +# CHECK: <_start>: +# CHECK-NEXT: 102d4: { immext(#0x420100) +# CHECK-NEXT: r2 = add(pc,##0x420130) } +# CHECK-NEXT: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10018) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10010) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: : +# CHECK-NEXT: 4102f8: { immext(#0xfffeffc0) +# CHECK-NEXT: r0 = add(r2,##-0x10008) } +# CHECK-NEXT: { call 0x410360 <__tls_get_addr@plt> } +# CHECK-NEXT: { jumpr r31 } + +## Verify PLT entries are created for TLS +# CHECK: Disassembly of section .plt: +# CHECK: <.plt>: +# CHECK-NEXT: 410310: { immext(#0x200c0) +# CHECK-NEXT: r28 = add(pc,##0x200f4) } +# CHECK-NEXT: { r14 -= add(r28,#0x10) +# CHECK-NEXT: r15 = memw(r28+#0x8) +# CHECK-NEXT: r28 = memw(r28+#0x4) } +# CHECK-NEXT: { r14 = asr(r14,#0x2) +# CHECK-NEXT: jumpr r28 } +# CHECK-NEXT: { trap0(#0xdb) } + +# CHECK: : +# CHECK-NEXT: 410340: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200d8) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: : +# CHECK-NEXT: 410350: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200cc) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: <__tls_get_addr@plt>: +# CHECK-NEXT: 410360: { immext(#0x200c0) +# CHECK-NEXT: r14 = add(pc,##0x200c0) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } diff --git a/lld/test/ELF/hexagon-thunk-range-plt.s b/lld/test/ELF/hexagon-thunk-range-plt.s new file mode 100644 index 0000000000000..3a8f50b681d81 --- /dev/null +++ b/lld/test/ELF/hexagon-thunk-range-plt.s @@ -0,0 +1,75 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf external.s -o external.o +# RUN: ld.lld -shared external.o -soname external.so -o external.so +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o +# RUN: ld.lld main.o external.so -o test +# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s + +## Test thunk range scenarios for Hexagon R_HEX_PLT_B22_PCREL relocations. +## PLT calls use the same ±8MB range as regular calls but go through PLT entries. +## This test verifies thunk generation for PLT calls at range boundaries. + +#--- external.s +.globl extern_within_range, extern_beyond_range, extern_close +.type extern_within_range, @function +.type extern_beyond_range, @function +.type extern_close, @function + +extern_within_range: + jumpr r31 + +extern_beyond_range: + jumpr r31 + +extern_close: + jumpr r31 + +#--- main.s +.globl _start +.type _start, @function +_start: + ## Test PLT calls to external functions at various ranges + call extern_within_range@PLT + call extern_beyond_range@PLT + call extern_close@PLT + jumpr r31 + +.skip 0x200000 + +# CHECK: Disassembly of section .text: +# CHECK: <_start>: +# CHECK-NEXT: 2021c: { call 0x220250 } +# CHECK-NEXT: { call 0x220260 } +# CHECK-NEXT: { call 0x220270 } +# CHECK-NEXT: { jumpr r31 } + +## Verify PLT header and entries are created with exact addresses +# CHECK: Disassembly of section .plt: +# CHECK: <.plt>: +# CHECK-NEXT: 220230: { immext(#0x20080) +# CHECK-NEXT: r28 = add(pc,##0x200b8) } +# CHECK-NEXT: { r14 -= add(r28,#0x10) +# CHECK-NEXT: r15 = memw(r28+#0x8) +# CHECK-NEXT: r28 = memw(r28+#0x4) } +# CHECK-NEXT: { r14 = asr(r14,#0x2) +# CHECK-NEXT: jumpr r28 } +# CHECK-NEXT: { trap0(#0xdb) } + +# CHECK: : +# CHECK-NEXT: 220250: { immext(#0x20080) +# CHECK-NEXT: r14 = add(pc,##0x200a8) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: : +# CHECK-NEXT: 220260: { immext(#0x20080) +# CHECK-NEXT: r14 = add(pc,##0x2009c) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } + +# CHECK: : +# CHECK-NEXT: 220270: { immext(#0x20080) +# CHECK-NEXT: r14 = add(pc,##0x20090) } +# CHECK-NEXT: { r28 = memw(r14+#0x0) } +# CHECK-NEXT: { jumpr r28 } diff --git a/lld/test/ELF/hexagon-thunks-packets.s b/lld/test/ELF/hexagon-thunks-packets.s new file mode 100644 index 0000000000000..c8aaad4341ff3 --- /dev/null +++ b/lld/test/ELF/hexagon-thunks-packets.s @@ -0,0 +1,122 @@ +# REQUIRES: hexagon +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-linux-musl %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d %t 2>&1 | \ +# RUN: FileCheck --check-prefixes=CHECK-NONPIC,CHECK %s +# RUN: llvm-mc -filetype=obj \ +# RUN: -triple=hexagon-unknown-linux-musl %s -o %t.o +# RUN: ld.lld --pie %t.o -o %t +# RUN: llvm-objdump -d %t 2>&1 | \ +# RUN: FileCheck --check-prefixes=CHECK-PIC,CHECK %s + +## Packets with pc-relative relocations are more interesting because +## the offset must be relative to the start of the source, destination +## packets and not necessarily the instruction word containing the jump/call. + +# CHECK: Disassembly of section .text: + +# CHECK-NONPIC: 000200b4 <__hexagon_thunk_myfn_a_from_.text.thunk>: +# CHECK-NONPIC: { immext(#0x1000040) +# CHECK-NONPIC: jump 0x1020110 } + +# CHECK-PIC: 00010150 <__hexagon_thunk_myfn_a_from_.text.thunk>: +# CHECK-PIC-NEXT: { immext(#0x1000040) +# CHECK-PIC-NEXT: r14 = add(pc,##0x1000060) } +# CHECK-PIC-NEXT: { jumpr r14 } + +# CHECK-NONPIC: 000200bc : +# CHECK-NONPIC: { jumpr r31 } +# CHECK-PIC: 0001015c : +# CHECK-PIC: { jumpr r31 } + .globl myfn_b + .type myfn_b, @function +myfn_b: + jumpr r31 + .size myfn_b, .-myfn_b + +# CHECK-PIC: 00010160
: + .globl main + .type main, @function +main: + { r0 = #0 + call myfn_a } +# CHECK-PIC: { call 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NONPIC: { call 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NEXT: r0 = #0x0 } + call myfn_a +# CHECK-PIC: call 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NONPIC: call 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> + call myfn_b +# CHECK-PIC-NEXT: call 0x1015c +# CHECK-NONPIC-NEXT: call 0x200bc + + { r2 = add(r0, r1) + if (p0) call #myfn_b + if (!p0) call #myfn_a } +# CHECK-PIC-NEXT: { if (p0) call 0x1015c +# CHECK-PIC-NEXT: if (!p0) call 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NONPIC-NEXT: { if (p0) call 0x200bc +# CHECK-NONPIC-NEXT: if (!p0) call 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> + +# CHECK-NEXT: r2 = add(r0,r1) } + + { r2 = add(r0, r1) + if (p0) call #myfn_a + if (!p0) call #myfn_a } +# CHECK-PIC-NEXT: { if (p0) call 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-PIC-NEXT: if (!p0) call 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NONPIC-NEXT: { if (p0) call 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NONPIC-NEXT: if (!p0) call 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NEXT: r2 = add(r0,r1) } + + { r2 = add(r0, r1) + r1 = r4 + r4 = r5 + if (r0 == #0) jump:t #myfn_a } +# CHECK-PIC-NEXT: { if (r0==#0) jump:t 0x10150 +# CHECK-NONPIC-NEXT: { if (r0==#0) jump:t 0x200b4 +# CHECK-NEXT: r2 = add(r0,r1) +# CHECK-NEXT: r1 = r4; r4 = r5 } + + { r2 = add(r0, r1) + r4 = r5 + if (r0 <= #0) jump:t #myfn_a + p1 = cmp.eq(r0, #0); if (p1.new) jump:nt #myfn_a } +# CHECK-NONPIC-NEXT: { if (r0<=#0) jump:t 0x200b4 +# CHECK-NONPIC-NEXT: p1 = cmp.eq(r0,#0x0); if (p1.new) jump:nt 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-PIC-NEXT: { if (r0<=#0) jump:t 0x10150 +# CHECK-PIC-NEXT: p1 = cmp.eq(r0,#0x0); if (p1.new) jump:nt 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> +# CHECK-NEXT: r2 = add(r0,r1) +# CHECK-NEXT: r4 = r5 } + + {r0 = #0; jump #myfn_a} +# CHECK-PIC-NEXT: { r0 = #0x0 ; jump 0x10150 <__hexagon_thunk_myfn_a_from_.text.thunk> } +# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x200b4 <__hexagon_thunk_myfn_a_from_.text.thunk> } + {r0 = #0; jump #myfn_b} +# CHECK-PIC-NEXT: { r0 = #0x0 ; jump 0x1015c } +# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x200bc } + jumpr r31 + .size main, .-main + + .section .text.foo + .skip 0x1000000 + + .globl myfn_a + .type myfn_a, @function +myfn_a: + {r0 = #0; jump #myfn_b} + jumpr r31 + .size myfn_a, .-myfn_a + +# CHECK-NONPIC: 01020110 : +# CHECK-NONPIC-NEXT: { r0 = #0x0 ; jump 0x1020118 <__hexagon_thunk_myfn_b_from_.text.thunk> } +# CHECK-NONPIC-NEXT: { jumpr r31 } + +# CHECK-NONPIC: 01020118 <__hexagon_thunk_myfn_b_from_.text.thunk>: +# CHECK-NONPIC-NEXT: { immext(#0xfeffff80) +# CHECK-NONPIC-NEXT: jump 0x200bc } + +# CHECK-PIC: 010101b8 <__hexagon_thunk_myfn_b_from_.text.thunk>: +# CHECK-PIC-NEXT: { immext(#0xfeffff80) +# CHECK-PIC-NEXT: r14 = add(pc,##0xfeffffa4) } +# CHECK-PIC-NEXT: { jumpr r14 } diff --git a/lld/test/ELF/hexagon-thunks.s b/lld/test/ELF/hexagon-thunks.s new file mode 100644 index 0000000000000..211074e1784b9 --- /dev/null +++ b/lld/test/ELF/hexagon-thunks.s @@ -0,0 +1,53 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %t/a.s -o %t/a.o +# RUN: ld.lld -T %t/lds %t/a.o -o %t/a +# RUN: llvm-objdump -d --no-show-raw-insn %t/a 2>&1 | \ +# RUN: FileCheck --check-prefixes=CHECK-NONPIC,CHECK %s +# RUN: llvm-mc -filetype=obj \ +# RUN: -triple=hexagon-unknown-elf %t/a.s -o %t/a.o + +# RUN: ld.lld -T %t/lds --pie %t/a.o -o %t/a +# RUN: llvm-objdump -d --no-show-raw-insn %t/a 2>&1 | \ +# RUN: FileCheck --check-prefixes=CHECK-PIC,CHECK %s + +#--- a.s +.section .text_low, "ax", %progbits + .globl main + .type main, @function +main: + call myfn + jumpr r31 + .size main, .-main + +.section .text_high, "ax", %progbits + .globl myfn + .type myfn, @function +myfn: + jumpr r31 + .size myfn, .-myfn + +# CHECK: Disassembly of section .text_low: + +# CHECK: <__hexagon_thunk_myfn_from_.text.thunk>: +# CHECK-NONPIC-NEXT: 200b4: { immext(#0x1000000) +# CHECK-NONPIC-NEXT: jump 0x10200bc } +# CHECK-PIC-NEXT: 200b4: { immext(#0x1000000) +# CHECK-PIC-NEXT: r14 = add(pc,##0x1000008) } +# CHECK-PIC-NEXT: { jumpr r14 } + +# CHECK-NONPIC:
: +# CHECK-NONPIC-NEXT: 200bc: { call 0x200b4 <__hexagon_thunk_myfn_from_.text.thunk> } +# CHECK-PIC:
: +# CHECK-PIC-NEXT: 200c0: { call 0x200b4 <__hexagon_thunk_myfn_from_.text.thunk> } +# CHECK-NEXT: { jumpr r31 } + +# CHECK: Disassembly of section .text_high: +# CHECK: : +# CHECK-NEXT: 10200bc: { jumpr r31 } + +#--- lds +SECTIONS { + .text_low 0x200b4: { *(.text_low) } + .text_high 0x10200bc : { *(.text_high) } +} diff --git a/lld/test/ELF/hexagon-tls-allocateaux-multiple.s b/lld/test/ELF/hexagon-tls-allocateaux-multiple.s new file mode 100644 index 0000000000000..a77cc822e67d4 --- /dev/null +++ b/lld/test/ELF/hexagon-tls-allocateaux-multiple.s @@ -0,0 +1,36 @@ +# REQUIRES: hexagon +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf a.s -o a.o +# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf b.s -o b.o +# RUN: ld.lld -shared a.o b.o -o out.so +# RUN: llvm-readobj -r out.so | FileCheck --check-prefix=RELOC %s + +#--- a.s +.globl _start +.type _start, @function + +_start: + r2 = add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) + r0 = add(r2,##tls_var@GDGOT) + call tls_var@GDPLT + jumpr r31 + +.section .tdata,"awT",@progbits +.globl tls_var +.type tls_var, @object +tls_var: + .word 0x1234 + +#--- b.s +.globl other_func +.type other_func, @function + +other_func: + ## Direct call to __tls_get_addr - this creates another path that may + ## try to allocate auxiliary data for the same symbol + call __tls_get_addr + jumpr r31 + +# RELOC: Section ({{.*}}) .rela.plt { +# RELOC: R_HEX_JMP_SLOT __tls_get_addr 0x0 +# RELOC: } diff --git a/lld/test/ELF/hexagon-tls-gd-xform.s b/lld/test/ELF/hexagon-tls-gd-xform.s index 65aeb118fcb33..ade54e8a16fad 100644 --- a/lld/test/ELF/hexagon-tls-gd-xform.s +++ b/lld/test/ELF/hexagon-tls-gd-xform.s @@ -18,10 +18,10 @@ _start: .ifdef GDPLT call x@gdplt -# CHECK_GDPLT: 101ec: { call 0x10220 } +# CHECK_GDPLT: 101ec: { call 0x10220 <__tls_get_addr@plt> } .else call x -# CHECK: 101b8: { call 0x101e0 } +# CHECK: 101b8: { call 0x101e0 } .endif # CHECK_GDPLT: 10220: { immext(#0x20040) diff --git a/lld/test/ELF/linkerscript/orphan-relocation.s b/lld/test/ELF/linkerscript/orphan-relocation.s new file mode 100644 index 0000000000000..adf5cac6c3e82 --- /dev/null +++ b/lld/test/ELF/linkerscript/orphan-relocation.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 +## Test that orphan section placement can handle a relocatable link where +## the relocation section is seen before the relocated section. + +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +## In a.ro, .rela.text precedes its relocated section. +# RUN: ld.lld -r a.o -T 1.lds -o a.ro +# RUN: llvm-readelf -S a.ro | FileCheck %s +# CHECK: .rela.text RELA +# CHECK-NEXT: .text PROGBITS + +# RUN: llvm-objcopy --rename-section .text=.com.text --rename-section .rela.text=.rela.com.text a.ro a1.o + +## Regression test for #156354 , where we added an orphan RELA section before its relocated section. +# RUN: ld.lld -r a1.o -o a1.ro +# RUN: llvm-readelf -S a1.ro | FileCheck %s --check-prefix=CHECK1 +# CHECK1: .com.text PROGBITS +# CHECK1-NEXT: .rela.com.text RELA + +#--- a.s +.globl foo +foo: + call foo + +#--- 1.lds +SECTIONS { + .rela.text 0 : { *(.rela.text) } + .text 0 : { *(.text) } +} diff --git a/lld/test/ELF/loongarch-pc-hi20-lo12-got.s b/lld/test/ELF/loongarch-pc-hi20-lo12-got.s new file mode 100644 index 0000000000000..acd94007d0ffc --- /dev/null +++ b/lld/test/ELF/loongarch-pc-hi20-lo12-got.s @@ -0,0 +1,145 @@ +# REQUIRES: loongarch +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc --filetype=obj --triple=loongarch64 a.s -o a.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 unpaired.s -o unpaired.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 lone-ldr.s -o lone-ldr.o + +# RUN: ld.lld a.o -T within-range.t -o a +# RUN: llvm-objdump -d --no-show-raw-insn a | FileCheck %s + +## This test verifies the encoding when the register $a0 is used. +# CHECK: pcalau12i $a0, 0 +# CHECK-NEXT: addi.d $a0, $a0, -2048 + +## PCALAU12I contains a nonzero addend, no relaxations should be applied. +# CHECK-NEXT: pcalau12i $a1, 2 +# CHECK-NEXT: ld.d $a1, $a1, -2048 + +## LD contains a nonzero addend, no relaxations should be applied. +# CHECK-NEXT: pcalau12i $a2, 2 +# CHECK-NEXT: ld.d $a2, $a2, -2040 + +## PCALAU12I and LD use different registers, no relaxations should be applied. +# CHECK-NEXT: pcalau12i $a3, 2 +# CHECK-NEXT: ld.d $a4, $a3, -2048 + +## PCALAU12I and LD use different registers, no relaxations should be applied. +# CHECK-NEXT: pcalau12i $a5, 2 +# CHECK-NEXT: ld.d $a5, $a6, -2048 + +# RUN: ld.lld a.o -T underflow-range.t -o a-underflow +# RUN: llvm-objdump -d --no-show-raw-insn a-underflow | FileCheck --check-prefix=OUTRANGE %s + +# RUN: ld.lld a.o -T overflow-range.t -o a-overflow +# RUN: llvm-objdump -d --no-show-raw-insn a-overflow | FileCheck --check-prefix=OUTRANGE %s + +# OUTRANGE: pcalau12i $a0, 1 +# OUTRANGE-NEXT: ld.d $a0, $a0, 0 + +## Relocations do not appear in pairs, no relaxations should be applied. +# RUN: ld.lld unpaired.o -T within-range.t -o unpaired +# RUN: llvm-objdump --no-show-raw-insn -d unpaired | FileCheck --check-prefix=UNPAIRED %s + +# UNPAIRED: pcalau12i $a0, 2 +# UNPAIRED-NEXT: b 8 +# UNPAIRED-NEXT: pcalau12i $a0, 2 +# UNPAIRED: ld.d $a0, $a0, -2048 + +## Relocations do not appear in pairs, no relaxations should be applied. +# RUN: ld.lld lone-ldr.o -T within-range.t -o lone-ldr +# RUN: llvm-objdump --no-show-raw-insn -d lone-ldr | FileCheck --check-prefix=LONE-LDR %s + +# LONE-LDR: ld.d $a0, $a0, -2048 + +## 32-bit code is mostly the same. We only test a few variants. +# RUN: llvm-mc --filetype=obj --triple=loongarch32 a.32.s -o a.32.o +# RUN: ld.lld a.32.o -T within-range.t -o a32 +# RUN: llvm-objdump -d --no-show-raw-insn a32 | FileCheck --check-prefix=CHECK32 %s + +## This test verifies the encoding when the register $a0 is used. +# CHECK32: pcalau12i $a0, 0 +# CHECK32-NEXT: addi.w $a0, $a0, -2048 + + +## This linker script ensures that .rodata and .text are sufficiently close to +## each other so that the pcalau12i + ld pair can be relaxed to pcalau12i + add. +#--- within-range.t +SECTIONS { + .rodata 0x1800: { *(.rodata) } + .text 0x2800: { *(.text) } + .got 0x3800: { *(.got) } +} + +## This linker script ensures that .rodata and .text are sufficiently far apart +## so that the pcalau12i + ld pair cannot be relaxed to pcalau12i + add. +#--- underflow-range.t +SECTIONS { + .rodata 0x800-4: { *(.rodata) } + .got 0x80002000: { *(.got) } + .text 0x80001000: { *(.text) } /* (0x800-4)+2GB+0x800+4 */ +} + +#--- overflow-range.t +SECTIONS { + .text 0x1000: { *(.text) } + .got 0x2000: { *(.got) } + .rodata 0x80000800 : { *(.rodata) } /* 0x1000+2GB-0x800 */ +} + +#--- a.s +## Symbol 'x' is nonpreemptible, the optimization should be applied. +.rodata +.hidden x +x: +.word 10 + +.text +.global _start +_start: + pcalau12i $a0, %got_pc_hi20(x) + ld.d $a0, $a0, %got_pc_lo12(x) + pcalau12i $a1, %got_pc_hi20(x+1) + ld.d $a1, $a1, %got_pc_lo12(x) + pcalau12i $a2, %got_pc_hi20(x) + ld.d $a2, $a2, %got_pc_lo12(x+8) + pcalau12i $a3, %got_pc_hi20(x) + ld.d $a4, $a3, %got_pc_lo12(x) + pcalau12i $a5, %got_pc_hi20(x) + ld.d $a5, $a6, %got_pc_lo12(x) + +#--- unpaired.s +.text +.hidden x +x: + nop +.global _start +_start: + pcalau12i $a0, %got_pc_hi20(x) + b L + pcalau12i $a0, %got_pc_hi20(x) +L: + ld.d $a0, $a0, %got_pc_lo12(x) + +#--- lone-ldr.s +.text +.hidden x +x: + nop +.global _start +_start: + ld.d $a0, $a0, %got_pc_lo12(x) + + +#--- a.32.s +## Symbol 'x' is nonpreemptible, the optimization should be applied. +.rodata +.hidden x +x: +.word 10 + +.text +.global _start +_start: + pcalau12i $a0, %got_pc_hi20(x) + ld.w $a0, $a0, %got_pc_lo12(x) diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s index a417d89e9fa2e..08d5d3e950d84 100644 --- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s +++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s @@ -1,22 +1,23 @@ # REQUIRES: loongarch +# RUN: rm -rf %t && split-file %s %t && cd %t -# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o -# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax a.s -o a.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax a.s -o a.64.o -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32 -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -o %t.64 -# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck --check-prefixes=RELAX %s -# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck --check-prefixes=RELAX %s +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -o a.32 +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -o a.64 +# RUN: llvm-objdump -td --no-show-raw-insn a.32 | FileCheck --check-prefixes=RELAX %s +# RUN: llvm-objdump -td --no-show-raw-insn a.64 | FileCheck --check-prefixes=RELAX %s -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -shared -o %t.32s -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.64.o -shared -o %t.64s -# RUN: llvm-objdump -td --no-show-raw-insn %t.32s | FileCheck --check-prefixes=RELAX %s -# RUN: llvm-objdump -td --no-show-raw-insn %t.64s | FileCheck --check-prefixes=RELAX %s +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.32.o -shared -o a.32s +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 a.64.o -shared -o a.64s +# RUN: llvm-objdump -td --no-show-raw-insn a.32s | FileCheck --check-prefixes=RELAX %s +# RUN: llvm-objdump -td --no-show-raw-insn a.64s | FileCheck --check-prefixes=RELAX %s -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.32.o -o %t.32o -# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 %t.64.o -o %t.64o -# RUN: llvm-objdump -td --no-show-raw-insn %t.32o | FileCheck --check-prefixes=NORELAX32 %s -# RUN: llvm-objdump -td --no-show-raw-insn %t.64o | FileCheck --check-prefixes=NORELAX64 %s +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.32.o -o a.32o +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x410000 a.64.o -o a.64o +# RUN: llvm-objdump -td --no-show-raw-insn a.32o | FileCheck --check-prefixes=NORELAX32 %s +# RUN: llvm-objdump -td --no-show-raw-insn a.64o | FileCheck --check-prefixes=NORELAX64 %s # RELAX-LABEL: <_start>: ## offset = 0x14000 - 0x10000 = 4096<<2 @@ -30,25 +31,46 @@ ## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0 # NORELAX32-NEXT: 10000: pcalau12i $a0, 1024 # NORELAX32-NEXT: addi.w $a0, $a0, 0 +## Not relaxation, convertion to PCRel. # NORELAX32-NEXT: pcalau12i $a0, 1024 -# NORELAX32-NEXT: ld.w $a0, $a0, 4 +# NORELAX32-NEXT: addi.w $a0, $a0, 0 # NORELAX32-NEXT: pcalau12i $a0, 1024 # NORELAX32-NEXT: addi.w $a0, $a0, 0 # NORELAX32-NEXT: pcalau12i $a0, 1024 -# NORELAX32-NEXT: ld.w $a0, $a0, 4 +# NORELAX32-NEXT: addi.w $a0, $a0, 0 # NORELAX64-LABEL: <_start>: ## offset exceed range of pcaddi ## offset = 0x410000 - 0x10000: 0x400 pages, page offset 0 # NORELAX64-NEXT: 10000: pcalau12i $a0, 1024 # NORELAX64-NEXT: addi.d $a0, $a0, 0 +## Not relaxation, convertion to PCRel. # NORELAX64-NEXT: pcalau12i $a0, 1024 -# NORELAX64-NEXT: ld.d $a0, $a0, 8 +# NORELAX64-NEXT: addi.d $a0, $a0, 0 # NORELAX64-NEXT: pcalau12i $a0, 1024 # NORELAX64-NEXT: addi.d $a0, $a0, 0 # NORELAX64-NEXT: pcalau12i $a0, 1024 -# NORELAX64-NEXT: ld.d $a0, $a0, 8 +# NORELAX64-NEXT: addi.d $a0, $a0, 0 + + +## GOT references with non-zero addends. No relaxation. +# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax nonzero.s -o nonzero.32.o +# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax nonzero.s -o nonzero.64.o +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.32.o -o nonzero.32 +# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 nonzero.64.o -o nonzero.64 +# RUN: llvm-objdump -td --no-show-raw-insn nonzero.32 | FileCheck --check-prefixes=NONZERO32 %s +# RUN: llvm-objdump -td --no-show-raw-insn nonzero.64 | FileCheck --check-prefixes=NONZERO64 %s + +# NONZERO32-LABEL: <_start>: +# NONZERO32-NEXT: 10000: pcalau12i $a0, 4 +# NONZERO32-NEXT: ld.w $a0, $a0, 8 + +# NONZERO64-LABEL: <_start>: +# NONZERO64-NEXT: 10000: pcalau12i $a0, 4 +# NONZERO64-NEXT: ld.d $a0, $a0, 12 + +#--- a.s .section .text .global _start _start: @@ -60,3 +82,14 @@ _start: .section .data sym: .zero 4 + + +#--- nonzero.s +.section .text +.global _start +_start: + la.got $a0, sym+4 + +.section .data +sym: + .zero 4 diff --git a/lld/test/ELF/loongarch-relax-tlsdesc.s b/lld/test/ELF/loongarch-relax-tlsdesc.s index 5f4368343471c..025cbc09fbdd8 100644 --- a/lld/test/ELF/loongarch-relax-tlsdesc.s +++ b/lld/test/ELF/loongarch-relax-tlsdesc.s @@ -9,7 +9,6 @@ # RUN: llvm-readobj -r -x .got a.64.so | FileCheck --check-prefix=GD64-RELA %s # RUN: llvm-objdump --no-show-raw-insn -dr -h a.64.so | FileCheck %s --check-prefix=GD64 -## FIXME: IE/LE relaxation have not yet been implemented, --relax/--no-relax obtain the same results. ## Transition from TLSDESC to IE/LE. Also check --emit-relocs. # RUN: ld.lld -e 0 -z now --emit-relocs a.64.o c.64.o -o a.64.le # RUN: llvm-readobj -r -x .got a.64.le 2>&1 | FileCheck --check-prefix=LE64-RELA %s @@ -73,25 +72,21 @@ # LE64-RELA: could not find section '.got' ## a@tprel = 0x8 -# LE64: 20158: nop +# LE64: 20158: ori $a0, $zero, 8 # LE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 a # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: nop # LE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 a # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: nop # LE64-NEXT: R_LARCH_TLS_DESC_LD a # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: ori $a0, $zero, 8 # LE64-NEXT: R_LARCH_TLS_DESC_CALL a # LE64-NEXT: R_LARCH_RELAX *ABS* # LE64-NEXT: add.d $a1, $a0, $tp ## b@tprel = 0x7ff -# LE64: 2016c: nop +# LE64: 20160: nop # LE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 b # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: nop # LE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 b # LE64-NEXT: nop # LE64-NEXT: R_LARCH_TLS_DESC_LD b @@ -101,7 +96,7 @@ ## c@tprel = 0x800 ## Without R_LARCH_RELAX relocation. No relaxation. -# LE64: 20180: nop +# LE64: 20170: nop # LE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 c # LE64-NEXT: addi.d $t0, $zero, 0 # LE64-NEXT: nop @@ -115,13 +110,11 @@ # LE64-NEXT: add.d $a3, $a0, $tp ## d@tprel = 0x1000 -# LE64: 201a0: nop +# LE64: 20190: lu12i.w $a0, 1 # LE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 d # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: nop # LE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 d # LE64-NEXT: R_LARCH_RELAX *ABS* -# LE64-NEXT: lu12i.w $a0, 1 # LE64-NEXT: R_LARCH_TLS_DESC_LD d # LE64-NEXT: ori $a0, $a0, 0 # LE64-NEXT: R_LARCH_TLS_DESC_CALL d @@ -160,35 +153,31 @@ # LE64-NORELAX-NEXT: add.d $a4, $a0, $tp # IE64-RELA: .rela.dyn { -# IE64-RELA-NEXT: 0x30408 R_LARCH_TLS_TPREL64 c 0x0 -# IE64-RELA-NEXT: 0x30410 R_LARCH_TLS_TPREL64 d 0x0 +# IE64-RELA-NEXT: 0x303F0 R_LARCH_TLS_TPREL64 c 0x0 +# IE64-RELA-NEXT: 0x303F8 R_LARCH_TLS_TPREL64 d 0x0 # IE64-RELA-NEXT: } # IE64-RELA: Hex dump of section '.got': -# IE64-RELA-NEXT: 0x00030408 00000000 00000000 00000000 00000000 . +# IE64-RELA-NEXT: 0x000303f0 00000000 00000000 00000000 00000000 . -# IE64: .got 00000010 0000000000030408 +# IE64: .got 00000010 00000000000303f0 ## a and b are optimized to use LE. c and d are optimized to IE. ## a@tprel = 0x8 -# IE64: 202c8: nop +# IE64: 202c8: ori $a0, $zero, 8 # IE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 a # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: nop # IE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 a # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: nop # IE64-NEXT: R_LARCH_TLS_DESC_LD a # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: ori $a0, $zero, 8 # IE64-NEXT: R_LARCH_TLS_DESC_CALL a # IE64-NEXT: R_LARCH_RELAX *ABS* # IE64-NEXT: add.d $a1, $a0, $tp ## b@tprel = 0x7ff -# IE64: 202dc: nop +# IE64: 202d0: nop # IE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 b # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: nop # IE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 b # IE64-NEXT: nop # IE64-NEXT: R_LARCH_TLS_DESC_LD b @@ -196,9 +185,9 @@ # IE64-NEXT: R_LARCH_TLS_DESC_CALL b # IE64-NEXT: add.d $a2, $a0, $tp -## &.got[c]-. = 0x30408 - 0x20300: 0x10 pages, page offset 0x408 +## &.got[c]-. = 0x303f0 - 0x202f0: 0x10 pages, page offset 0x3f0 ## Without R_LARCH_RELAX relocation. No relaxation. -# IE64: 202f0: nop +# IE64: 202e0: nop # IE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 c # IE64-NEXT: addi.d $t0, $zero, 0 # IE64-NEXT: nop @@ -207,20 +196,18 @@ # IE64-NEXT: pcalau12i $a0, 16 # IE64-NEXT: R_LARCH_TLS_DESC_LD c # IE64-NEXT: addi.d $t0, $t0, 1 -# IE64-NEXT: ld.d $a0, $a0, 1032 +# IE64-NEXT: ld.d $a0, $a0, 1008 # IE64-NEXT: R_LARCH_TLS_DESC_CALL c # IE64-NEXT: add.d $a3, $a0, $tp -## &.got[d]-. = 0x30408+8 - 0x20318: 0x10 pages, page offset 0x410 -# IE64: 20310: nop +## &.got[d]-. = 0x303f0+8 - 0x20300: 0x10 pages, page offset 0x3f8 +# IE64: 20300: pcalau12i $a0, 16 # IE64-NEXT: R_LARCH_TLS_DESC_PC_HI20 d # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: nop # IE64-NEXT: R_LARCH_TLS_DESC_PC_LO12 d # IE64-NEXT: R_LARCH_RELAX *ABS* -# IE64-NEXT: pcalau12i $a0, 16 # IE64-NEXT: R_LARCH_TLS_DESC_LD d -# IE64-NEXT: ld.d $a0, $a0, 1040 +# IE64-NEXT: ld.d $a0, $a0, 1016 # IE64-NEXT: R_LARCH_TLS_DESC_CALL d # IE64-NEXT: add.d $a4, $a0, $tp diff --git a/lldb/docs/use/mcp.md b/lldb/docs/use/mcp.md index 375c164fe771c..b7474246b54f3 100644 --- a/lldb/docs/use/mcp.md +++ b/lldb/docs/use/mcp.md @@ -75,7 +75,69 @@ Configuration example for [Visual Studio Code](https://code.visualstudio.com/doc } ``` -### Troubleshooting +## Tools + +Tools are a primitive in the Model Context Protocol that enable servers to +expose functionality to clients. + +LLDB's MCP integration exposes one tool, named `lldb_command` which allows the +model to run the same commands a user would type in the LLDB command +interpreter. It takes two arguments: + +1. The unique debugger ID as a number. +2. The command and its arguments as a string. + +## Resources + +Resources are a primitive in the Model Context Protocol that allow servers to +expose content that can be read by clients. + +LLDB's MCP integration exposes a resource for each debugger and target +instance. Debugger resources are accessible using the following URI: + +``` +lldb://debugger/ +``` + +Example output: + +```json +{ + "contents": [ + { + "uri": "lldb://debugger/1", + "mimeType": "application/json", + "text": "{\"debugger_id\":1,\"name\":\"debugger_1\",\"num_targets\":1}" + } + ] +} +``` + +Debuggers can contain one or more targets, which are accessible using the +following URI: + +``` +lldb://debugger//target/ +``` + +Example output: + +```json +{ + "contents": [ + { + "uri": "lldb://debugger/1/target/0", + "mimeType": "application/json", + "text": "{\"arch\":\"arm64-apple-macosx26.0.0\",\"debugger_id\":1,\"dummy\":false,\"path\":\"/bin/count\",\"platform\":\"host\",\"selected\":true,\"target_idx\":0}" + } + ] +} +``` + +Note that unlike the debugger id, which is unique, the target index is not +stable and may be reused when a target is removed and a new target is added. + +## Troubleshooting The MCP server uses the `Host` log channel. You can enable logging with the `log enable` command. diff --git a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h index 5345160850914..dafa41c11327a 100644 --- a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h +++ b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h @@ -24,6 +24,9 @@ class InstrumentationRuntimeStopInfo : public StopInfo { return lldb::eStopReasonInstrumentation; } + std::optional + GetSuggestedStackFrameIndex(bool inlined_stack) override; + const char *GetDescription() override; bool DoShouldNotify(Event *event_ptr) override { return true; } diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h index 8a66296346f2d..8d455dc831df3 100644 --- a/lldb/include/lldb/Target/StackFrameList.h +++ b/lldb/include/lldb/Target/StackFrameList.h @@ -46,6 +46,9 @@ class StackFrameList { /// Mark a stack frame as the currently selected frame and return its index. uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); + /// Resets the selected frame index of this object. + void ClearSelectedFrameIndex(); + /// Get the currently selected frame index. /// We should only call SelectMostRelevantFrame if (a) the user hasn't already /// selected a frame, and (b) if this really is a user facing @@ -172,6 +175,15 @@ class StackFrameList { /// The currently selected frame. An optional is used to record whether anyone /// has set the selected frame on this stack yet. We only let recognizers /// change the frame if this is the first time GetSelectedFrame is called. + /// + /// Thread-safety: + /// This member is not protected by a mutex. + /// LLDB really only should have an opinion about the selected frame index + /// when a process stops, before control gets handed back to the user. + /// After that, it's up to them to change it whenever they feel like it. + /// If two parts of lldb decided they wanted to be in control of the selected + /// frame index on stop the right way to fix it would need to be some explicit + /// negotiation for who gets to control this. std::optional m_selected_frame_idx; /// The number of concrete frames fetched while filling the frame list. This diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 6ede7fa301a82..688c056da2633 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -479,6 +479,11 @@ class Thread : public std::enable_shared_from_this, bool SetSelectedFrameByIndexNoisily(uint32_t frame_idx, Stream &output_stream); + /// Resets the selected frame index of this object. + void ClearSelectedFrameIndex() { + return GetStackFrameList()->ClearSelectedFrameIndex(); + } + void SetDefaultFileAndLineToSelectedFrame() { GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame(); } diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index a4ff96e4158ce..a47ffabdecd0e 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1380,6 +1380,9 @@ def isAArch64SMEFA64(self): def isAArch64MTE(self): return self.isAArch64() and "mte" in self.getCPUInfo() + def isAArch64MTEStoreOnly(self): + return self.isAArch64() and "mtestoreonly" in self.getCPUInfo() + def isAArch64GCS(self): return self.isAArch64() and "gcs" in self.getCPUInfo() diff --git a/lldb/packages/Python/lldbsuite/test/make/libcxx-simulators-common/compressed_pair.h b/lldb/packages/Python/lldbsuite/test/make/libcxx-simulators-common/compressed_pair.h index 35649b10ce45e..a1aa7e1a69f3e 100644 --- a/lldb/packages/Python/lldbsuite/test/make/libcxx-simulators-common/compressed_pair.h +++ b/lldb/packages/Python/lldbsuite/test/make/libcxx-simulators-common/compressed_pair.h @@ -4,6 +4,14 @@ #include #include // for std::forward +// COMPRESSED_PAIR_REV versions: +// 0 -> Post-c88580c layout +// 1 -> Post-27c83382d83dc layout +// 2 -> Post-769c42f4a552a layout +// 3 -> Post-f5e687d7bf49c layout +// 4 -> padding-less no_unique_address-based layout (introduced in +// 27c83382d83dc) + namespace std { namespace __lldb { @@ -13,7 +21,50 @@ namespace __lldb { #define _LLDB_NO_UNIQUE_ADDRESS [[__no_unique_address__]] #endif -#if COMPRESSED_PAIR_REV == 0 // Post-c88580c layout +// From libc++ datasizeof.h +template struct _FirstPaddingByte { + _LLDB_NO_UNIQUE_ADDRESS _Tp __v_; + char __first_padding_byte_; +}; + +template +inline const size_t __datasizeof_v = + __builtin_offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_); + +template +struct __lldb_is_final : public integral_constant {}; + +// The legacy layout has been patched, see +// https://github.com/llvm/llvm-project/pull/142516. +#if COMPRESSED_PAIR_REV == 1 +template class __compressed_pair_padding { + char __padding_[((is_empty<_ToPad>::value && + !__lldb_is_final<_ToPad>::value) || + is_reference<_ToPad>::value) + ? 0 + : sizeof(_ToPad) - __datasizeof_v<_ToPad>]; +}; +#elif COMPRESSED_PAIR_REV > 1 && COMPRESSED_PAIR_REV < 4 +template +inline const bool __is_reference_or_unpadded_object = + (std::is_empty<_ToPad>::value && !__lldb_is_final<_ToPad>::value) || + sizeof(_ToPad) == __datasizeof_v<_ToPad>; + +template +inline const bool __is_reference_or_unpadded_object<_Tp &> = true; + +template +inline const bool __is_reference_or_unpadded_object<_Tp &&> = true; + +template > +class __compressed_pair_padding { + char __padding_[sizeof(_ToPad) - __datasizeof_v<_ToPad>] = {}; +}; + +template class __compressed_pair_padding<_ToPad, true> {}; +#endif // COMPRESSED_PAIR_REV == 1 + +#if COMPRESSED_PAIR_REV == 0 struct __value_init_tag {}; struct __default_init_tag {}; @@ -59,49 +110,6 @@ class __compressed_pair : private __compressed_pair_elem<_T1, 0>, _T1 &first() { return static_cast<_Base1 &>(*this).__get(); } }; #elif COMPRESSED_PAIR_REV == 1 || COMPRESSED_PAIR_REV == 2 -// From libc++ datasizeof.h -template struct _FirstPaddingByte { - _LLDB_NO_UNIQUE_ADDRESS _Tp __v_; - char __first_padding_byte_; -}; - -template -inline const size_t __datasizeof_v = - __builtin_offsetof(_FirstPaddingByte<_Tp>, __first_padding_byte_); - -template -struct __lldb_is_final : public integral_constant {}; - -// The legacy layout has been patched, see -// https://github.com/llvm/llvm-project/pull/142516. -#if COMPRESSED_PAIR_REV == 1 -template class __compressed_pair_padding { - char __padding_[((is_empty<_ToPad>::value && - !__lldb_is_final<_ToPad>::value) || - is_reference<_ToPad>::value) - ? 0 - : sizeof(_ToPad) - __datasizeof_v<_ToPad>]; -}; -#else -template -inline const bool __is_reference_or_unpadded_object = - (std::is_empty<_ToPad>::value && !__lldb_is_final<_ToPad>::value) || - sizeof(_ToPad) == __datasizeof_v<_ToPad>; - -template -inline const bool __is_reference_or_unpadded_object<_Tp &> = true; - -template -inline const bool __is_reference_or_unpadded_object<_Tp &&> = true; - -template > -class __compressed_pair_padding { - char __padding_[sizeof(_ToPad) - __datasizeof_v<_ToPad>] = {}; -}; - -template class __compressed_pair_padding<_ToPad, true> {}; -#endif - #define _LLDB_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ [[__gnu__::__aligned__( \ alignof(T2))]] _LLDB_NO_UNIQUE_ADDRESS T1 Initializer1; \ @@ -119,6 +127,27 @@ template class __compressed_pair_padding<_ToPad, true> {}; _LLDB_NO_UNIQUE_ADDRESS T3 Initializer3; \ _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding3_; #elif COMPRESSED_PAIR_REV == 3 +#define _LLDB_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \ + struct { \ + [[__gnu__::__aligned__( \ + alignof(T2))]] _LLDB_NO_UNIQUE_ADDRESS T1 Initializer1; \ + _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding1_; \ + _LLDB_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding2_; \ + } + +#define _LLDB_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, \ + Initializer3) \ + struct { \ + [[using __gnu__: __aligned__(alignof(T2)), \ + __aligned__(alignof(T3))]] _LLDB_NO_UNIQUE_ADDRESS T1 Initializer1; \ + _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding1_; \ + _LLDB_NO_UNIQUE_ADDRESS T2 Initializer2; \ + _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding2_; \ + _LLDB_NO_UNIQUE_ADDRESS T3 Initializer3; \ + _LLDB_NO_UNIQUE_ADDRESS __compressed_pair_padding __padding3_; \ + } +#elif COMPRESSED_PAIR_REV == 4 #define _LLDB_COMPRESSED_PAIR(T1, Name1, T2, Name2) \ _LLDB_NO_UNIQUE_ADDRESS T1 Name1; \ _LLDB_NO_UNIQUE_ADDRESS T2 Name2 @@ -127,7 +156,7 @@ template class __compressed_pair_padding<_ToPad, true> {}; _LLDB_NO_UNIQUE_ADDRESS T1 Name1; \ _LLDB_NO_UNIQUE_ADDRESS T2 Name2; \ _LLDB_NO_UNIQUE_ADDRESS T3 Name3 -#endif +#endif // COMPRESSED_PAIR_REV == 3 } // namespace __lldb } // namespace std diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp index a1de895c0ba98..c0b10797e506a 100644 --- a/lldb/source/Host/windows/MainLoopWindows.cpp +++ b/lldb/source/Host/windows/MainLoopWindows.cpp @@ -14,6 +14,7 @@ #include "llvm/Config/llvm-config.h" #include "llvm/Support/WindowsError.h" #include +#include #include #include #include @@ -222,7 +223,7 @@ MainLoopWindows::RegisterReadObject(const IOObjectSP &object_sp, if (m_read_fds.find(waitable_handle) != m_read_fds.end()) { error = Status::FromErrorStringWithFormat( - "File descriptor %d already monitored.", waitable_handle); + "File descriptor %p already monitored.", waitable_handle); return nullptr; } @@ -234,7 +235,7 @@ MainLoopWindows::RegisterReadObject(const IOObjectSP &object_sp, } else { DWORD file_type = GetFileType(waitable_handle); if (file_type != FILE_TYPE_PIPE) { - error = Status::FromErrorStringWithFormat("Unsupported file type %d", + error = Status::FromErrorStringWithFormat("Unsupported file type %ld", file_type); return nullptr; } diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp index 0b495fff69dfa..001396fafde04 100644 --- a/lldb/source/Host/windows/PipeWindows.cpp +++ b/lldb/source/Host/windows/PipeWindows.cpp @@ -279,7 +279,8 @@ llvm::Expected PipeWindows::Read(void *buf, size_t size, return Status(failure_error, eErrorTypeWin32).takeError(); DWORD timeout_msec = - timeout ? ceil(*timeout).count() : INFINITE; + timeout ? std::chrono::ceil(*timeout).count() + : INFINITE; DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout_msec); if (wait_result != WAIT_OBJECT_0) { @@ -324,7 +325,8 @@ llvm::Expected PipeWindows::Write(const void *buf, size_t size, return Status(failure_error, eErrorTypeWin32).takeError(); DWORD timeout_msec = - timeout ? ceil(*timeout).count() : INFINITE; + timeout ? std::chrono::ceil(*timeout).count() + : INFINITE; DWORD wait_result = ::WaitForSingleObject(m_write_overlapped.hEvent, timeout_msec); if (wait_result != WAIT_OBJECT_0) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 2529e78f78bca..633b860b5784c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -1053,6 +1053,16 @@ ClangASTImporter::MapCompleter::~MapCompleter() = default; llvm::Expected ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { + // FIXME: The Minimal import mode of clang::ASTImporter does not correctly + // import Lambda definitions. Work around this for now by not importing + // lambdas at all. This is most likely encountered when importing decls from + // the `std` module (not from debug-info), where lambdas can be defined in + // inline function bodies. Those will be imported by LLDB. + if (const auto *CXX = llvm::dyn_cast(From)) + if (CXX->isLambda()) + return llvm::make_error( + ASTImportError::UnsupportedConstruct); + if (m_std_handler) { std::optional D = m_std_handler->Import(From); if (D) { diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 9a869f3ea0289..862082f8a16ba 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -790,31 +790,27 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { lldb_private::formatters::LibcxxStringSummaryProviderASCII, "std::string summary provider", "^std::__[[:alnum:]]+::basic_string, " - "std::__[[:alnum:]]+::allocator >$", + "std::__[[:alnum:]]+::char_traits,.*>$", stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxStringSummaryProviderASCII, "std::string summary provider", "^std::__[[:alnum:]]+::basic_string, " - "std::__[[:alnum:]]+::allocator >$", + "std::__[[:alnum:]]+::char_traits,.*>$", stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxStringSummaryProviderUTF16, "std::u16string summary provider", "^std::__[[:alnum:]]+::basic_string, " - "std::__[[:alnum:]]+::allocator >$", + "std::__[[:alnum:]]+::char_traits,.*>$", stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxStringSummaryProviderUTF32, "std::u32string summary provider", "^std::__[[:alnum:]]+::basic_string, " - "std::__[[:alnum:]]+::allocator >$", + "std::__[[:alnum:]]+::char_traits,.*>$", stl_summary_flags, true); AddCXXSummary(cpp_category_sp, @@ -825,8 +821,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider", "^std::__[[:alnum:]]+::basic_string, " - "std::__[[:alnum:]]+::allocator >$", + "std::__[[:alnum:]]+::char_traits,.*>$", stl_summary_flags, true); AddCXXSummary(cpp_category_sp, @@ -1342,24 +1337,16 @@ static void RegisterStdStringSummaryProvider( category_sp->AddTypeSummary(makeSpecifier(string_ty), summary_sp); - // std::basic_string category_sp->AddTypeSummary( makeSpecifier(llvm::formatv("std::basic_string<{}>", char_ty).str()), summary_sp); - // std::basic_string,std::allocator > - category_sp->AddTypeSummary( - makeSpecifier(llvm::formatv("std::basic_string<{0},std::char_traits<{0}>," - "std::allocator<{0}> >", - char_ty) - .str()), - summary_sp); - // std::basic_string, std::allocator > + category_sp->AddTypeSummary( - makeSpecifier( - llvm::formatv("std::basic_string<{0}, std::char_traits<{0}>, " - "std::allocator<{0}> >", + std::make_shared( + llvm::formatv("^std::basic_string<{0}, ?std::char_traits<{0}>,.*>$", char_ty) - .str()), + .str(), + eFormatterMatchRegex), summary_sp); } @@ -1382,20 +1369,17 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp->AddTypeSummary("std::__cxx11::string", eFormatterMatchExact, string_summary_sp); cpp_category_sp->AddTypeSummary( - "std::__cxx11::basic_string, " - "std::allocator >", - eFormatterMatchExact, string_summary_sp); - cpp_category_sp->AddTypeSummary("std::__cxx11::basic_string, " - "std::allocator >", - eFormatterMatchExact, string_summary_sp); + "^std::__cxx11::basic_string,.*>$", + eFormatterMatchRegex, string_summary_sp); + cpp_category_sp->AddTypeSummary("^std::__cxx11::basic_string,.*>$", + eFormatterMatchRegex, string_summary_sp); cpp_category_sp->AddTypeSummary("std::__cxx11::wstring", eFormatterMatchExact, string_summary_sp); cpp_category_sp->AddTypeSummary( - "std::__cxx11::basic_string, " - "std::allocator >", - eFormatterMatchExact, string_summary_sp); + "^std::__cxx11::basic_string,.*>$", + eFormatterMatchRegex, string_summary_sp); SyntheticChildren::Flags stl_synth_flags; stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences( diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index a7874047942c4..6053d042b29b1 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -49,11 +49,6 @@ static void consumeInlineNamespace(llvm::StringRef &name) { } } -bool lldb_private::formatters::isOldCompressedPairLayout( - ValueObject &pair_obj) { - return isStdTemplate(pair_obj.GetTypeName(), "__compressed_pair"); -} - bool lldb_private::formatters::isStdTemplate(ConstString type_name, llvm::StringRef type) { llvm::StringRef name = type_name.GetStringRef(); @@ -105,6 +100,44 @@ lldb_private::formatters::GetSecondValueOfLibCXXCompressedPair( return value; } +std::pair +lldb_private::formatters::GetValueOrOldCompressedPair( + ValueObject &obj, size_t anon_struct_idx, llvm::StringRef child_name, + llvm::StringRef compressed_pair_name) { + auto is_old_compressed_pair = [](ValueObject &pair_obj) -> bool { + return isStdTemplate(pair_obj.GetTypeName(), "__compressed_pair"); + }; + + // Try searching the child member in an anonymous structure first. + if (auto unwrapped = obj.GetChildAtIndex(anon_struct_idx)) { + ValueObjectSP node_sp(obj.GetChildMemberWithName(child_name)); + if (node_sp) + return {node_sp, is_old_compressed_pair(*node_sp)}; + } + + // Older versions of libc++ don't wrap the children in anonymous structures. + // Try that instead. + ValueObjectSP node_sp(obj.GetChildMemberWithName(child_name)); + if (node_sp) + return {node_sp, is_old_compressed_pair(*node_sp)}; + + // Try the even older __compressed_pair layout. + + assert(!compressed_pair_name.empty()); + + node_sp = obj.GetChildMemberWithName(compressed_pair_name); + + // Unrecognized layout (possibly older than LLDB supports). + if (!node_sp) + return {nullptr, false}; + + // Expected old compressed_pair layout, but got something else. + if (!is_old_compressed_pair(*node_sp)) + return {nullptr, false}; + + return {node_sp, true}; +} + bool lldb_private::formatters::LibcxxFunctionSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { @@ -205,11 +238,12 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider( if (!valobj_sp) return false; - ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_")); + auto [ptr_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + *valobj_sp, /*anon_struct_idx=*/0, "__ptr_", "__ptr_"); if (!ptr_sp) return false; - if (isOldCompressedPairLayout(*ptr_sp)) + if (is_compressed_pair) ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp); if (!ptr_sp) @@ -379,13 +413,14 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { if (!valobj_sp) return lldb::ChildCacheState::eRefetch; - ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_")); + auto [ptr_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + *valobj_sp, /*anon_struct_idx=*/0, "__ptr_", "__ptr_"); if (!ptr_sp) return lldb::ChildCacheState::eRefetch; // Retrieve the actual pointer and the deleter, and clone them to give them // user-friendly names. - if (isOldCompressedPairLayout(*ptr_sp)) { + if (is_compressed_pair) { if (ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp)) m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer")); @@ -424,17 +459,15 @@ enum class StringLayout { CSD, DSC }; } static ValueObjectSP ExtractLibCxxStringData(ValueObject &valobj) { - if (auto rep_sp = valobj.GetChildMemberWithName("__rep_")) - return rep_sp; - - ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_"); - if (!valobj_r_sp || !valobj_r_sp->GetError().Success()) + auto [valobj_r_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + valobj, /*anon_struct_idx=*/0, "__rep_", "__r_"); + if (!valobj_r_sp) return nullptr; - if (!isOldCompressedPairLayout(*valobj_r_sp)) - return nullptr; + if (is_compressed_pair) + return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp); - return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp); + return valobj_r_sp; } /// Determine the size in bytes of \p valobj (a libc++ std::string object) and diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index d88a6ecb1fa89..819f8a985f9b9 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -25,7 +25,22 @@ GetChildMemberWithName(ValueObject &obj, lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair); lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair); -bool isOldCompressedPairLayout(ValueObject &pair_obj); + +/// Returns the ValueObjectSP of the child of \c obj. If \c obj has no +/// child named \c child_name, returns the __compressed_pair child instead +/// with \c compressed_pair_name, if one exists. +/// +/// Latest libc++ wrap the compressed children in an anonymous structure. +/// The \c anon_struct_idx indicates the location of this struct. +/// +/// The returned boolean is \c true if the returned child was has an old-style +/// libc++ __compressed_pair layout. +/// +/// If no child was found returns a nullptr. +std::pair +GetValueOrOldCompressedPair(ValueObject &obj, size_t anon_struct_idx, + llvm::StringRef child_name, + llvm::StringRef compressed_pair_name); bool isStdTemplate(ConstString type_name, llvm::StringRef type); bool LibcxxStringSummaryProviderASCII( diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 826e6ab090e10..dfc23266fc148 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -297,11 +297,18 @@ lldb::ChildCacheState ForwardListFrontEnd::Update() { if (err.Fail() || !backend_addr) return lldb::ChildCacheState::eRefetch; - ValueObjectSP impl_sp(m_backend.GetChildMemberWithName("__before_begin_")); + auto list_base_sp = m_backend.GetChildAtIndex(0); + if (!list_base_sp) + return lldb::ChildCacheState::eRefetch; + + // Anonymous strucutre index is in base class at index 0. + auto [impl_sp, is_compressed_pair] = + GetValueOrOldCompressedPair(*list_base_sp, /*anon_struct_idx=*/0, + "__before_begin_", "__before_begin_"); if (!impl_sp) return ChildCacheState::eRefetch; - if (isOldCompressedPairLayout(*impl_sp)) + if (is_compressed_pair) impl_sp = GetFirstValueOfLibCXXCompressedPair(*impl_sp); if (!impl_sp) @@ -324,17 +331,10 @@ llvm::Expected ListFrontEnd::CalculateNumChildren() { if (!m_head || !m_tail || m_node_address == 0) return 0; - ValueObjectSP size_node_sp(m_backend.GetChildMemberWithName("__size_")); - if (!size_node_sp) { - size_node_sp = m_backend.GetChildMemberWithName( - "__size_alloc_"); // pre-compressed_pair rework - - if (!isOldCompressedPairLayout(*size_node_sp)) - return llvm::createStringError("Unexpected std::list layout: expected " - "old __compressed_pair layout."); - + auto [size_node_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + m_backend, /*anon_struct_idx=*/1, "__size_", "__size_alloc_"); + if (is_compressed_pair) size_node_sp = GetFirstValueOfLibCXXCompressedPair(*size_node_sp); - } if (size_node_sp) m_count = size_node_sp->GetValueAsUnsigned(UINT32_MAX); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index 41441dfbc7180..85766966f1554 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -200,7 +200,8 @@ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd { llvm::Expected GetIndexOfChildWithName(ConstString name) override; private: - llvm::Expected CalculateNumChildrenForOldCompressedPairLayout(); + llvm::Expected + CalculateNumChildrenForOldCompressedPairLayout(ValueObject &pair); /// Returns the ValueObject for the __tree_node type that /// holds the key/value pair of the node at index \ref idx. @@ -254,16 +255,8 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: llvm::Expected lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: - CalculateNumChildrenForOldCompressedPairLayout() { - ValueObjectSP node_sp(m_tree->GetChildMemberWithName("__pair3_")); - if (!node_sp) - return 0; - - if (!isOldCompressedPairLayout(*node_sp)) - return llvm::createStringError("Unexpected std::map layout: expected " - "old __compressed_pair layout."); - - node_sp = GetFirstValueOfLibCXXCompressedPair(*node_sp); + CalculateNumChildrenForOldCompressedPairLayout(ValueObject &pair) { + auto node_sp = GetFirstValueOfLibCXXCompressedPair(pair); if (!node_sp) return 0; @@ -281,12 +274,16 @@ llvm::Expected lldb_private::formatters:: if (m_tree == nullptr) return 0; - if (auto node_sp = m_tree->GetChildMemberWithName("__size_")) { - m_count = node_sp->GetValueAsUnsigned(0); - return m_count; - } + auto [size_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + *m_tree, /*anon_struct_idx=*/2, "__size_", "__pair3_"); + if (!size_sp) + return llvm::createStringError("Unexpected std::map layout"); - return CalculateNumChildrenForOldCompressedPairLayout(); + if (is_compressed_pair) + return CalculateNumChildrenForOldCompressedPairLayout(*size_sp); + + m_count = size_sp->GetValueAsUnsigned(0); + return m_count; } ValueObjectSP diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 501fd0945b82c..f88a5319068a2 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -130,22 +130,17 @@ CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: CompilerType lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: GetNodeType() { - auto node_sp = m_backend.GetChildAtNamePath({"__table_", "__first_node_"}); - - if (!node_sp) { - auto p1_sp = m_backend.GetChildAtNamePath({"__table_", "__p1_"}); - if (!p1_sp) - return {}; + auto table_sp = m_backend.GetChildMemberWithName("__table_"); + if (!table_sp) + return {}; - if (!isOldCompressedPairLayout(*p1_sp)) - return {}; + auto [node_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + *table_sp, /*anon_struct_idx=*/1, "__first_node_", "__p1_"); + if (is_compressed_pair) + node_sp = GetFirstValueOfLibCXXCompressedPair(*node_sp); - node_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - if (!node_sp) - return {}; - } - - assert(node_sp); + if (!node_sp) + return {}; return node_sp->GetCompilerType().GetTypeTemplateArgument(0).GetPointeeType(); } @@ -223,19 +218,15 @@ lldb::ValueObjectSP lldb_private::formatters:: llvm::Expected lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: CalculateNumChildrenImpl(ValueObject &table) { - if (auto size_sp = table.GetChildMemberWithName("__size_")) + auto [size_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + table, /*anon_struct_idx=*/2, "__size_", "__p2_"); + if (!is_compressed_pair && size_sp) return size_sp->GetValueAsUnsigned(0); - ValueObjectSP p2_sp = table.GetChildMemberWithName("__p2_"); - if (!p2_sp) - return llvm::createStringError( - "Unexpected std::unordered_map layout: __p2_ member not found."); + if (!is_compressed_pair) + return llvm::createStringError("Unsupported std::unordered_map layout."); - if (!isOldCompressedPairLayout(*p2_sp)) - return llvm::createStringError("Unexpected std::unordered_map layout: old " - "__compressed_pair layout not found."); - - ValueObjectSP num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*p2_sp); + ValueObjectSP num_elements_sp = GetFirstValueOfLibCXXCompressedPair(*size_sp); if (!num_elements_sp) return llvm::createStringError( @@ -246,19 +237,13 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: } static ValueObjectSP GetTreePointer(ValueObject &table) { - ValueObjectSP tree_sp = table.GetChildMemberWithName("__first_node_"); - if (!tree_sp) { - ValueObjectSP p1_sp = table.GetChildMemberWithName("__p1_"); - if (!p1_sp) - return nullptr; - - if (!isOldCompressedPairLayout(*p1_sp)) - return nullptr; - - tree_sp = GetFirstValueOfLibCXXCompressedPair(*p1_sp); - if (!tree_sp) - return nullptr; - } + auto [tree_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + table, /*anon_struct_idx=*/1, "__first_node_", "__p1_"); + if (is_compressed_pair) + tree_sp = GetFirstValueOfLibCXXCompressedPair(*tree_sp); + + if (!tree_sp) + return nullptr; return tree_sp->GetChildMemberWithName("__next_"); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 4bcdf01c221a3..60913e5c1ac56 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -126,17 +126,15 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex( } static ValueObjectSP GetDataPointer(ValueObject &root) { - if (auto cap_sp = root.GetChildMemberWithName("__cap_")) - return cap_sp; - - ValueObjectSP cap_sp = root.GetChildMemberWithName("__end_cap_"); + auto [cap_sp, is_compressed_pair] = GetValueOrOldCompressedPair( + root, /*anon_struct_idx=*/2, "__cap_", "__end_cap_"); if (!cap_sp) return nullptr; - if (!isOldCompressedPairLayout(*cap_sp)) - return nullptr; + if (is_compressed_pair) + return GetFirstValueOfLibCXXCompressedPair(*cap_sp); - return GetFirstValueOfLibCXXCompressedPair(*cap_sp); + return cap_sp; } lldb::ChildCacheState diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp index 7adc00622ec2d..d21dac221aa22 100644 --- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp +++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp @@ -44,7 +44,8 @@ NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( NativeProcessFreeBSD &process = native_thread.GetProcess(); g_register_flags_detector.DetectFields( process.GetAuxValue(AuxVector::AUXV_FREEBSD_AT_HWCAP).value_or(0), - process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0)); + process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0), + /*hwcap3=*/0); } return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread); diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 884c7d4b9e359..b1c7421bef8d5 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -162,10 +162,13 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS); + std::optional auxv_at_hwcap3 = + process.GetAuxValue(AuxVector::AUXV_AT_HWCAP3); std::lock_guard lock(g_register_flags_detector_mutex); if (!g_register_flags_detector.HasDetected()) g_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0), - auxv_at_hwcap2.value_or(0)); + auxv_at_hwcap2.value_or(0), + auxv_at_hwcap3.value_or(0)); auto register_info_up = std::make_unique(target_arch, opt_regsets); diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.cpp b/lldb/source/Plugins/Process/Utility/AuxVector.cpp index f495ffb1924e7..50500a8593e1d 100644 --- a/lldb/source/Plugins/Process/Utility/AuxVector.cpp +++ b/lldb/source/Plugins/Process/Utility/AuxVector.cpp @@ -84,6 +84,7 @@ const char *AuxVector::GetEntryName(EntryType type) const { case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break; case ENTRY_NAME(AUXV_AT_RANDOM); break; case ENTRY_NAME(AUXV_AT_HWCAP2); break; + case ENTRY_NAME(AUXV_AT_HWCAP3); break; case ENTRY_NAME(AUXV_AT_EXECFN); break; case ENTRY_NAME(AUXV_AT_SYSINFO); break; case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break; diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h index 2670b34f6b0af..7733e0ffc6832 100644 --- a/lldb/source/Plugins/Process/Utility/AuxVector.h +++ b/lldb/source/Plugins/Process/Utility/AuxVector.h @@ -57,6 +57,7 @@ class AuxVector { AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms. AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes. AUXV_AT_HWCAP2 = 26, ///< Extension of AT_HWCAP. + AUXV_AT_HWCAP3 = 29, ///< Extension of AT_HWCAP. AUXV_AT_EXECFN = 31, ///< Filename of executable. AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system /// calls and other nice things. diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp index 042940b7dff6e..330a24af67c4e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp @@ -26,11 +26,15 @@ #define HWCAP2_EBF16 (1ULL << 32) #define HWCAP2_FPMR (1ULL << 48) +#define HWCAP3_MTE_STORE_ONLY (1ULL << 1) + using namespace lldb_private; Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { (void)hwcap; + (void)hwcap3; if (!(hwcap2 & HWCAP2_FPMR)) return {}; @@ -53,8 +57,10 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) { Arm64RegisterFlagsDetector::Fields Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap, - uint64_t hwcap2) { + uint64_t hwcap2, + uint64_t hwcap3) { (void)hwcap2; + (void)hwcap3; if (!(hwcap & HWCAP_GCS)) return {}; @@ -67,8 +73,10 @@ Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap, } Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { (void)hwcap; + (void)hwcap3; if (!(hwcap2 & HWCAP2_SME)) return {}; @@ -83,8 +91,8 @@ Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) { } Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, - uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { (void)hwcap; if (!(hwcap2 & HWCAP2_MTE)) @@ -94,16 +102,29 @@ Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines // used to build the value. + std::vector fields; + fields.reserve(4); + if (hwcap3 & HWCAP3_MTE_STORE_ONLY) + fields.push_back({"STORE_ONLY", 19}); + static const FieldEnum tcf_enum( "tcf_enum", {{0, "TCF_NONE"}, {1, "TCF_SYNC"}, {2, "TCF_ASYNC"}, {3, "TCF_ASYMM"}}); - return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT. - {"TCF", 1, 2, &tcf_enum}, - {"TAGGED_ADDR_ENABLE", 0}}; + + fields.insert( + std::end(fields), + {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT. + {"TCF", 1, 2, &tcf_enum}, + {"TAGGED_ADDR_ENABLE", 0}}); + + return fields; } Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { + (void)hwcap3; + static const FieldEnum rmode_enum( "rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}}); @@ -142,10 +163,12 @@ Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) { } Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { // fpsr's contents are constant. (void)hwcap; (void)hwcap2; + (void)hwcap3; return { // Bits 31-28 are N/Z/C/V, only used by AArch32. @@ -162,7 +185,10 @@ Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) { } Arm64RegisterFlagsDetector::Fields -Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) { +Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { + (void)hwcap3; + // The fields here are a combination of the Arm manual's SPSR_EL1, // plus a few changes where Linux has decided not to make use of them at all, // or at least not from userspace. @@ -207,9 +233,10 @@ Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) { return cpsr_fields; } -void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) { +void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { for (auto ® : m_registers) - reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2)); + reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2, hwcap3)); m_has_detected = true; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h index 7daebcc71db04..aec2bf9f4886f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h @@ -40,7 +40,7 @@ class Arm64RegisterFlagsDetector { /// If called more than once, fields will be redetected each time from /// scratch. If the target would not have this register at all, the list of /// fields will be left empty. - void DetectFields(uint64_t hwcap, uint64_t hwcap2); + void DetectFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3); /// Add the field information of any registers named in this class, /// to the relevant RegisterInfo instances. Note that this will be done @@ -53,15 +53,22 @@ class Arm64RegisterFlagsDetector { private: using Fields = std::vector; - using DetectorFn = std::function; + using DetectorFn = std::function; - static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2); - static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2); + static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); + static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); struct RegisterEntry { RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector) diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 27530f032ce51..0fecefe23b88e 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -666,7 +666,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) { target->ModulesDidUnload(unloaded_modules, true); } - SetProcessExitStatus(GetID(), true, 0, exit_code); + SetExitStatus(exit_code, /*exit_string=*/""); SetPrivateState(eStateExited); ProcessDebugger::OnExitProcess(exit_code); diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index bd02bb0e69a4d..d5046d369ab2f 100644 --- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -96,14 +96,19 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( llvm::Triple::OSType os = process->GetArchitecture().GetTriple().getOS(); if ((os == llvm::Triple::Linux) || (os == llvm::Triple::FreeBSD)) { AuxVector aux_vec(process->GetAuxvData()); - std::optional auxv_at_hwcap = aux_vec.GetAuxValue( - os == llvm::Triple::FreeBSD ? AuxVector::AUXV_FREEBSD_AT_HWCAP - : AuxVector::AUXV_AT_HWCAP); + bool is_freebsd = os == llvm::Triple::FreeBSD; + std::optional auxv_at_hwcap = + aux_vec.GetAuxValue(is_freebsd ? AuxVector::AUXV_FREEBSD_AT_HWCAP + : AuxVector::AUXV_AT_HWCAP); std::optional auxv_at_hwcap2 = aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2); + std::optional auxv_at_hwcap3 = + is_freebsd ? std::nullopt + : aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP3); m_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0), - auxv_at_hwcap2.value_or(0)); + auxv_at_hwcap2.value_or(0), + auxv_at_hwcap3.value_or(0)); m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(), GetRegisterCount()); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index c76d67b47b336..8916c58beec0f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2201,6 +2201,18 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, for (DelayedAddObjCClassProperty &property : delayed_properties) property.Finalize(); } + } else if (Language::LanguageIsObjC( + static_cast(die.GetAttributeValueAsUnsigned( + DW_AT_APPLE_runtime_class, eLanguageTypeUnknown)))) { + /// The forward declaration was C++ but the definition is Objective-C. + /// We currently don't handle such situations. In such cases, keep the + /// forward declaration without a definition to avoid violating Clang AST + /// invariants. + LLDB_LOG(GetLog(LLDBLog::Expressions), + "WARNING: Type completion aborted because forward declaration for " + "'{0}' is C++ while definition is Objective-C.", + llvm::StringRef(die.GetName())); + return {}; } if (!bases.empty()) { diff --git a/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp index 7f82581cc601e..aef895def7939 100644 --- a/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp +++ b/lldb/source/Target/InstrumentationRuntimeStopInfo.cpp @@ -8,13 +8,20 @@ #include "lldb/Target/InstrumentationRuntimeStopInfo.h" +#include "lldb/Core/Module.h" #include "lldb/Target/InstrumentationRuntime.h" #include "lldb/Target/Process.h" +#include "lldb/lldb-enumerations.h" #include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; +static bool IsStoppedInDarwinSanitizer(Thread &thread, Module &module) { + return module.GetFileSpec().GetFilename().GetStringRef().starts_with( + "libclang_rt."); +} + InstrumentationRuntimeStopInfo::InstrumentationRuntimeStopInfo( Thread &thread, std::string description, StructuredData::ObjectSP additional_data) @@ -34,3 +41,38 @@ InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( return StopInfoSP( new InstrumentationRuntimeStopInfo(thread, description, additionalData)); } + +std::optional +InstrumentationRuntimeStopInfo::GetSuggestedStackFrameIndex( + bool inlined_stack) { + ThreadSP thread_sp = GetThread(); + if (!thread_sp) + return std::nullopt; + + // Defensive upper-bound of when we stop walking up the frames in + // case we somehow ended up looking at an infinite recursion. + constexpr size_t max_stack_depth = 128; + + // Start at parent frame. + size_t stack_idx = 1; + StackFrameSP most_relevant_frame_sp = + thread_sp->GetStackFrameAtIndex(stack_idx); + + while (most_relevant_frame_sp && stack_idx <= max_stack_depth) { + auto const &sc = + most_relevant_frame_sp->GetSymbolContext(lldb::eSymbolContextModule); + + if (!sc.module_sp) + return std::nullopt; + + // Found a frame outside of the sanitizer runtime libraries. + // That's the one we want to display. + if (!IsStoppedInDarwinSanitizer(*thread_sp, *sc.module_sp)) + return stack_idx; + + ++stack_idx; + most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(stack_idx); + } + + return stack_idx; +} diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 2aa02fd58335e..a2fa88b569135 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -4257,6 +4257,14 @@ bool Process::ProcessEventData::ShouldStop(Event *event_ptr, // appropriately. We also need to stop processing actions, since they // aren't expecting the target to be running. + // Clear the selected frame which may have been set as part of utility + // expressions that have been run as part of this stop. If we didn't + // clear this, then StopInfo::GetSuggestedStackFrameIndex would not + // take affect when we next called SelectMostRelevantFrame. + // PerformAction should not be the one setting a selected frame, instead + // this should be done via GetSuggestedStackFrameIndex. + thread_sp->ClearSelectedFrameIndex(); + // FIXME: we might have run. if (stop_info_sp->HasTargetRunSinceMe()) { SetRestarted(true); diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 16cd2548c2784..931b73b1e3633 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -936,3 +936,5 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame, strm.IndentLess(); return num_frames_displayed; } + +void StackFrameList::ClearSelectedFrameIndex() { m_selected_frame_idx.reset(); } diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index 4aa9e046d6077..656503bb8d228 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -5,8 +5,8 @@ let Definition = "target_experimental" in { Global, DefaultTrue, Desc<"If true, inject local variables explicitly into the expression text. This will fix symbol resolution when there are name collisions between ivars and local variables. But it can make expressions run much more slowly.">; def UseDIL : Property<"use-DIL", "Boolean">, - Global, DefaultFalse, - Desc<"If true, use the alternative DIL implementation for frame variable evaluation.">; + Global, DefaultTrue, + Desc<"If true, use the DIL implementation for frame variable evaluation.">; } let Definition = "target" in { diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp index fd3f9f8724608..6f28434c646cd 100644 --- a/lldb/source/ValueObject/DILEval.cpp +++ b/lldb/source/ValueObject/DILEval.cpp @@ -303,7 +303,7 @@ Interpreter::Visit(const MemberOfNode *node) { } } - if (field_obj && field_obj->GetName() == node->GetFieldName()) { + if (field_obj) { if (m_use_dynamic != lldb::eNoDynamicValues) { lldb::ValueObjectSP dynamic_val_sp = field_obj->GetDynamicValue(m_use_dynamic); diff --git a/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/TestFrameVarDILQualifiedId.py b/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/TestFrameVarDILQualifiedId.py index b2ce9602e6a50..8c009aa182d07 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/TestFrameVarDILQualifiedId.py +++ b/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/TestFrameVarDILQualifiedId.py @@ -29,3 +29,17 @@ def test_frame_var(self): self.expect_var_path("ns::i", value="1") self.expect_var_path("::ns::ns::i", value="2") self.expect_var_path("ns::ns::i", value="2") + + self.expect_var_path("foo", value="1") + self.expect_var_path("::(anonymous namespace)::foo", value="13") + self.expect_var_path("(anonymous namespace)::foo", value="13") + self.expect_var_path("ns1::(anonymous namespace)::foo", value="5") + self.expect_var_path( + "(anonymous namespace)::ns2::(anonymous namespace)::foo", + value="7", + ) + self.expect_var_path("::ns1::(anonymous namespace)::foo", value="5") + self.expect_var_path( + "::(anonymous namespace)::ns2::(anonymous namespace)::foo", + value="7", + ) diff --git a/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/main.cpp index 8a5c47a6f364c..10ffa1e54a991 100644 --- a/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/main.cpp +++ b/lldb/test/API/commands/frame/var-dil/basics/QualifiedId/main.cpp @@ -10,7 +10,26 @@ int i = 2; } // namespace ns +namespace { +int foo = 13; +} + +namespace ns1 { +namespace { +int foo = 5; +} +} // namespace ns1 + +namespace { +namespace ns2 { +namespace { +int foo = 7; +} +} // namespace ns2 +} // namespace + int main(int argc, char **argv) { + int foo = 1; - return 0; // Set a breakpoint here + return foo + ::foo + ns1::foo + ns2::foo; // Set a breakpoint here } diff --git a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py index 2570f267bf46e..c003d87f8ca37 100644 --- a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py +++ b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py @@ -34,29 +34,41 @@ def test_mte_ctrl_register(self): substrs=["stop reason = breakpoint 1."], ) - def check_mte_ctrl(async_err, sync_err): + has_store_only = self.isAArch64MTEStoreOnly() + + def check_mte_ctrl(async_err, sync_err, store_only): # Bit 0 = tagged addressing enabled # Bit 1 = synchronous faults # Bit 2 = asynchronous faults - value = "0x{:016x}".format((async_err << 2) | (sync_err << 1) | 1) + # Bit 19 = store only checking mode + value = "0x{:016x}".format( + (store_only << 19) | (async_err << 2) | (sync_err << 1) | 1 + ) expected = [value] if self.hasXMLSupport(): + fields = "(" + if has_store_only: + fields += f"STORE_ONLY = {store_only}, " + tfc_modes = ["NONE", "SYNC", "ASYNC", "ASYMM"] - expected.append( - f"(TAGS = 0, TCF = TCF_{tfc_modes[async_err << 1 | sync_err]}, TAGGED_ADDR_ENABLE = 1)".format( - async_err, sync_err - ) - ) + fields += f"TAGS = 0, TCF = TCF_{tfc_modes[async_err << 1 | sync_err]}, TAGGED_ADDR_ENABLE = 1)" + + expected.append(fields) self.expect("register read mte_ctrl", substrs=expected) # We start enabled with synchronous faults. - check_mte_ctrl(0, 1) + check_mte_ctrl(0, 1, 0) # Change to asynchronous faults. self.runCmd("register write mte_ctrl 5") - check_mte_ctrl(1, 0) + check_mte_ctrl(1, 0, 0) # This would return to synchronous faults if we did not restore the # previous value. self.expect("expression setup_mte()", substrs=["= 0"]) - check_mte_ctrl(1, 0) + check_mte_ctrl(1, 0, 0) + + # Store only checking requires FEAT_MTE_STORE_ONLY. + if has_store_only: + self.runCmd(f"register write mte_ctrl {1 | (1 << 19)}") + check_mte_ctrl(0, 0, 1) diff --git a/lldb/test/API/functionalities/asan/TestMemoryHistory.py b/lldb/test/API/functionalities/asan/TestMemoryHistory.py index 1568140b355dc..302a45c2368de 100644 --- a/lldb/test/API/functionalities/asan/TestMemoryHistory.py +++ b/lldb/test/API/functionalities/asan/TestMemoryHistory.py @@ -2,7 +2,6 @@ Test that ASan memory history provider returns correct stack traces """ - import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -10,6 +9,7 @@ from lldbsuite.test import lldbutil from lldbsuite.test_event.build_exception import BuildError + class MemoryHistoryTestCase(TestBase): @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @expectedFailureNetBSD @@ -96,6 +96,11 @@ def libsanitizers_asan_tests(self): ) self.check_traces(skip_line_numbers=True) + if self.platformIsDarwin(): + # Make sure we're not stopped in the sanitizer library but instead at the + # point of failure in the user-code. + self.assertEqual(self.frame().GetFunctionName(), "main") + # do the same using SB API process = self.dbg.GetSelectedTarget().process val = ( @@ -220,6 +225,11 @@ def compiler_rt_asan_tests(self): self.check_traces() + if self.platformIsDarwin(): + # Make sure we're not stopped in the sanitizer library but instead at the + # point of failure in the user-code. + self.assertEqual(self.frame().GetFunctionName(), "main") + # make sure the 'memory history' command still works even when we're # generating a report now self.expect( diff --git a/lldb/test/API/functionalities/asan/TestReportData.py b/lldb/test/API/functionalities/asan/TestReportData.py index dd6834a01b80c..c832436b0f447 100644 --- a/lldb/test/API/functionalities/asan/TestReportData.py +++ b/lldb/test/API/functionalities/asan/TestReportData.py @@ -2,7 +2,6 @@ Test the AddressSanitizer runtime support for report breakpoint and data extraction. """ - import json import lldb from lldbsuite.test.decorators import * @@ -10,6 +9,7 @@ from lldbsuite.test import lldbutil from lldbsuite.test_event.build_exception import BuildError + class AsanTestReportDataCase(TestBase): @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @expectedFailureNetBSD @@ -67,6 +67,11 @@ def asan_tests(self, libsanitizers=False): lldb.eStopReasonInstrumentation, ) + if self.platformIsDarwin(): + # Make sure we're not stopped in the sanitizer library but instead at the + # point of failure in the user-code. + self.assertEqual(self.frame().GetFunctionName(), "main") + self.expect( "bt", "The backtrace should show the crashing line", diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py index 49c0c814f077a..8ce46ba3b8862 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/TestDataFormatterStdString.py @@ -80,6 +80,8 @@ def cleanup(): '(%s::string) Q = "quite a long std::strin with lots of info inside it"' % ns, "(%s::string *) null_str = nullptr" % ns, + '(CustomString) custom_str = "hello!"', + '(CustomWString) custom_wstr = L"hello!"', ], ) @@ -143,6 +145,10 @@ def do_test_multibyte(self): '(%s::u16string) u16_empty = u""' % ns, '(%s::u32string) u32_string = U"🍄🍅🍆🍌"' % ns, '(%s::u32string) u32_empty = U""' % ns, + '(CustomStringU16) custom_u16 = u"ß水氶"', + '(CustomStringU16) custom_u16_empty = u""', + '(CustomStringU32) custom_u32 = U"🍄🍅🍆🍌"', + '(CustomStringU32) custom_u32_empty = U""', ], ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp index f22c890861d01..577b78e35fc1f 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string/main.cpp @@ -1,6 +1,33 @@ +#include #include #include +template struct CustomAlloc { + using value_type = T; + using pointer = value_type *; + using const_pointer = const value_type *; + using size_type = std::size_t; + + pointer allocate(size_type n) { return (T *)malloc(n * sizeof(T)); } + + void deallocate(pointer p, size_type) { + if (p) + free(p); + } +}; + +using CustomString = + std::basic_string, CustomAlloc>; + +using CustomWString = + std::basic_string, CustomAlloc>; + +using CustomStringU16 = std::basic_string, + CustomAlloc>; + +using CustomStringU32 = std::basic_string, + CustomAlloc>; + size_t touch_string(std::string &in_str) { return in_str.size(); // Break here to look at bad string } @@ -99,8 +126,16 @@ int main() { std::string *pq = &q; std::string *pQ = &Q; + CustomString custom_str("hello!"); + CustomWString custom_wstr(L"hello!"); + CustomStringU16 custom_u16(u16_string.c_str()); + CustomStringU16 custom_u16_empty(u""); + CustomStringU32 custom_u32(u32_string.c_str()); + CustomStringU32 custom_u32_empty(U""); + S.assign(L"!!!!!"); // Set break point at this line. std::string *not_a_string = (std::string *)0x0; touch_string(*not_a_string); + return 0; } diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp index f10811817c0d2..5943b35deab8b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/invalid-vector/main.cpp @@ -1,4 +1,4 @@ -#define COMPRESSED_PAIR_REV 3 +#define COMPRESSED_PAIR_REV 4 #include namespace std { diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py index c8d9c2e389a05..f27fc2e3c4569 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py @@ -28,7 +28,7 @@ def _run_test(self, defines): for v in [None, "ALTERNATE_LAYOUT"]: for r in range(6): - for c in range(4): + for c in range(5): name = "test_r%d_c%d" % (r, c) defines = ["REVISION=%d" % r, "COMPRESSED_PAIR_REV=%d" % c] if v: diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/main.cpp index cf431e524069c..b19c051596705 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/main.cpp @@ -209,7 +209,7 @@ template class basic_string { __long &getLongRep() { #if COMPRESSED_PAIR_REV == 0 return __r_.first().__l; -#elif COMPRESSED_PAIR_REV <= 3 +#else return __rep_.__l; #endif } @@ -217,14 +217,14 @@ template class basic_string { __short &getShortRep() { #if COMPRESSED_PAIR_REV == 0 return __r_.first().__s; -#elif COMPRESSED_PAIR_REV <= 3 +#else return __rep_.__s; #endif } #if COMPRESSED_PAIR_REV == 0 std::__lldb::__compressed_pair<__rep, allocator_type> __r_; -#elif COMPRESSED_PAIR_REV <= 3 +#else _LLDB_COMPRESSED_PAIR(__rep, __rep_, allocator_type, __alloc_); #endif diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py index e623c3a1413b6..1e25ac9472034 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/TestDataFormatterLibcxxUniquePtrSimulator.py @@ -26,7 +26,7 @@ def _run_test(self, defines): ) -for r in range(4): +for r in range(5): name = "test_r%d" % r defines = ["COMPRESSED_PAIR_REV=%d" % r] diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp index 3d174a91cc262..bd840aaceffa9 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx-simulators/unique_ptr/main.cpp @@ -20,8 +20,7 @@ template > class unique_ptr { std::__lldb::__compressed_pair __ptr_; explicit unique_ptr(pointer __p) noexcept : __ptr_(__p, std::__lldb::__value_init_tag()) {} -#elif COMPRESSED_PAIR_REV == 1 || COMPRESSED_PAIR_REV == 2 || \ - COMPRESSED_PAIR_REV == 3 +#else _LLDB_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_); explicit unique_ptr(pointer __p) noexcept : __ptr_(__p), __deleter_() {} #endif diff --git a/lldb/test/API/functionalities/tsan/basic/TestTsanBasic.py b/lldb/test/API/functionalities/tsan/basic/TestTsanBasic.py index ca8b74e35dff6..51a28c5013071 100644 --- a/lldb/test/API/functionalities/tsan/basic/TestTsanBasic.py +++ b/lldb/test/API/functionalities/tsan/basic/TestTsanBasic.py @@ -63,11 +63,14 @@ def tsan_tests(self): substrs=["1 match found"], ) - # We should be stopped in __tsan_on_report process = self.dbg.GetSelectedTarget().process thread = process.GetSelectedThread() frame = thread.GetSelectedFrame() - self.assertIn("__tsan_on_report", frame.GetFunctionName()) + if self.platformIsDarwin(): + # We should not be stopped in the sanitizer library. + self.assertIn("f2", frame.GetFunctionName()) + else: + self.assertIn("__tsan_on_report", frame.GetFunctionName()) # The stopped thread backtrace should contain either line1 or line2 # from main.c. diff --git a/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py b/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py index 868a2864d2b5e..9e9ea2114196e 100644 --- a/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py +++ b/lldb/test/API/functionalities/ubsan/basic/TestUbsanBasic.py @@ -52,8 +52,11 @@ def ubsan_tests(self): substrs=["1 match found"], ) - # We should be stopped in __ubsan_on_report - self.assertIn("__ubsan_on_report", frame.GetFunctionName()) + if self.platformIsDarwin(): + # We should not be stopped in the sanitizer library. + self.assertIn("main", frame.GetFunctionName()) + else: + self.assertIn("__ubsan_on_report", frame.GetFunctionName()) # The stopped thread backtrace should contain either 'align line' found = False diff --git a/lldb/test/API/lang/cpp/lambdas/TestLambdas.py b/lldb/test/API/lang/cpp/lambdas/TestLambdas.py index c8308c16011e0..112f375c0ef2f 100644 --- a/lldb/test/API/lang/cpp/lambdas/TestLambdas.py +++ b/lldb/test/API/lang/cpp/lambdas/TestLambdas.py @@ -1,4 +1,12 @@ from lldbsuite.test import lldbinline from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals()) +lldbinline.MakeInlineTest( + __file__, + globals(), + [ + decorators.expectedFailureAll( + bugnumber="https://github.com/llvm/llvm-project/issues/149477" + ) + ], +) diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py index bfdc8229094f0..825e1a4b79fd2 100644 --- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py +++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py @@ -10,8 +10,8 @@ class AArch64LinuxMTEMemoryTagCoreFileTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True - MTE_BUF_ADDR = hex(0xFFFF82C74000) - BUF_ADDR = hex(0xFFFF82C73000) + MTE_BUF_ADDR = hex(0xFFFFA733B000) + BUF_ADDR = hex(0xFFFFA733A000) @skipIfLLVMTargetMissing("AArch64") def test_mte_tag_core_file_memory_region(self): @@ -215,7 +215,7 @@ def test_mte_tag_fault_reason(self): self.expect( "bt", substrs=[ - "* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address=0xffff82c74010)" + "* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address=0xffffa733b010)" ], ) @@ -231,12 +231,15 @@ def test_mte_ctrl_register(self): self.runCmd("target create --core core.mte") # The expected value is: # * Allowed tags value of 0xFFFF, shifted up by 3 resulting in 0x7fff8. + # * Bit 19 set to 0, which means that store only checking is disabled. # * Bit 1 set to enable synchronous tag faults. # * Bit 0 set to enable the tagged address ABI. expected = ["mte_ctrl = 0x000000000007fffb"] if self.hasXMLSupport(): - expected.append("(TAGS = 65535, TCF = TCF_SYNC, TAGGED_ADDR_ENABLE = 1)") + expected.append( + "(STORE_ONLY = 0, TAGS = 65535, TCF = TCF_SYNC, TAGGED_ADDR_ENABLE = 1)" + ) self.expect("register read mte_ctrl", substrs=expected) diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.mte b/lldb/test/API/linux/aarch64/mte_core_file/core.mte index 84a3266667e77..188d06d11c71e 100644 Binary files a/lldb/test/API/linux/aarch64/mte_core_file/core.mte and b/lldb/test/API/linux/aarch64/mte_core_file/core.mte differ diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.nomte b/lldb/test/API/linux/aarch64/mte_core_file/core.nomte index 201f2880e6dc2..454ff8361cc3f 100644 Binary files a/lldb/test/API/linux/aarch64/mte_core_file/core.nomte and b/lldb/test/API/linux/aarch64/mte_core_file/core.nomte differ diff --git a/lldb/test/API/linux/aarch64/mte_core_file/main.c b/lldb/test/API/linux/aarch64/mte_core_file/main.c index 6537edd7bdb95..597459459bb04 100644 --- a/lldb/test/API/linux/aarch64/mte_core_file/main.c +++ b/lldb/test/API/linux/aarch64/mte_core_file/main.c @@ -23,7 +23,7 @@ int main(int argc, char const *argv[]) { #ifdef NO_MTE - *(char *)(0) = 0; + __builtin_trap(); #endif if (prctl(PR_SET_TAGGED_ADDR_CTRL, diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 0d2774b281710..20a75f4076e42 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -131,7 +131,7 @@ def run_test_evaluate_expressions( self.assertEvaluateFailure("a_function(1)") self.assertEvaluateFailure("var2 + struct1.foo") self.assertEvaluateFailure("foo_func") - self.assertEvaluateFailure("foo_var") + self.assertEvaluate("foo_var", "44") # Expressions at breakpoint 2, which is an anonymous block self.continue_to_breakpoint(breakpoint_2) @@ -169,7 +169,7 @@ def run_test_evaluate_expressions( self.assertEvaluateFailure("a_function(1)") self.assertEvaluateFailure("var2 + struct1.foo") self.assertEvaluateFailure("foo_func") - self.assertEvaluateFailure("foo_var") + self.assertEvaluate("foo_var", "44") # Expressions at breakpoint 3, which is inside a_function self.continue_to_breakpoint(breakpoint_3) @@ -195,7 +195,7 @@ def run_test_evaluate_expressions( self.assertEvaluateFailure("a_function(1)") self.assertEvaluateFailure("list + 1") self.assertEvaluateFailure("foo_func") - self.assertEvaluateFailure("foo_var") + self.assertEvaluate("foo_var", "44") # Now we check that values are updated after stepping self.continue_to_breakpoint(breakpoint_4) diff --git a/lldb/test/Shell/Expr/TestLambdaExprImport.test b/lldb/test/Shell/Expr/TestLambdaExprImport.test new file mode 100644 index 0000000000000..c57ce06453fe2 --- /dev/null +++ b/lldb/test/Shell/Expr/TestLambdaExprImport.test @@ -0,0 +1,26 @@ +# Test that we can successfully ASTImport clang::LambdaExpr nodes. +# Currently this is not supported in MinimalImport mode (which LLDB +# uses always). + +# RUN: split-file %s %t +# RUN: %clang_host -g -gdwarf %t/main.cpp -o %t.out +# RUN: %lldb -o "settings set interpreter.stop-command-source-on-error false" \ +# RUN: -x -b -s %t/commands.input %t.out 2>&1 \ +# RUN: | FileCheck %s + +#--- main.cpp + +int main() { + __builtin_debugtrap(); +} + +#--- commands.input + +run +expression --top-level -- void method(int x) { [x=x] { ; }; } +target dump typesystem + +# CHECK: expression +# CHECK: target dump typesystem +# CHECK-NOT: FunctionDecl +# CHECK-NOT: LambdaExpr diff --git a/lldb/test/Shell/SymbolFile/DWARF/TestDedupWarnings.test b/lldb/test/Shell/SymbolFile/DWARF/TestDedupWarnings.test index d4fcf78d01b81..c29b51219d191 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/TestDedupWarnings.test +++ b/lldb/test/Shell/SymbolFile/DWARF/TestDedupWarnings.test @@ -15,7 +15,7 @@ # RUN: %clang_host -fmodules -Xclang -fmodules-cache-path=%t/cache -I%t -g -gmodules %t/b.m -o %t/b.o -c # RUN: %clang_host %t/a.o %t/b.o -o %t/a.out # RUN: rm -rf %t/cache -# RUN: %lldb %t/a.out -o "b main" -o run -o "p a" -o "p b" -o q 2>&1 | FileCheck %s +# RUN: %lldb %t/a.out -o "b main" -o run -o "expr a" -o "expr b" -o q 2>&1 | FileCheck %s # CHECK: {{[ab]}}.o{{.*}}/cache/{{.*}}/C-{{.*}}.pcm' does not exist # CHECK-NOT: /cache/{{.*}}/C-{.*}.pcm' does not exist # CHECK: {{[ab]}}.o{{.*}}/cache/{{.*}}/C-{{.*}}.pcm' does not exist diff --git a/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test b/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test new file mode 100644 index 0000000000000..30109c2943c9b --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/objcxx-forward-decls.test @@ -0,0 +1,70 @@ +# REQUIRES: system-darwin + +# In this test we have two CUs with conflicting forward declaration +# depending on the CU language (one is C++ and the other is Objective-C++). +# We are then stopped in the C++ CU and try to print the type, at which +# point LLDB will try to make it into an Clang AST node. If LLDB were to +# interpret the type as C++ instead of Objective-C, we'd violate Clang +# invariants and crash. +# +# RUN: split-file %s %t +# RUN: %clangxx_host -c -g -x objective-c++ %t/request.m -o %t/request_objc.o +# RUN: %clangxx_host -c -g %t/main.cpp -o %t/main.o +# RUN: %clangxx_host %t/main.o %t/request_objc.o -framework Foundation -o %t/a.out +# +# RUN: %lldb %t/a.out \ +# RUN: -o "breakpoint set -p return -X main" \ +# RUN: -o run \ +# RUN: -o "frame variable r" \ +# RUN: -o exit | FileCheck %s +# +# RUN: dsymutil %t/a.out +# +# RUN: %lldb %t/a.out \ +# RUN: -o "breakpoint set -p return -X main" \ +# RUN: -o run \ +# RUN: -o "frame variable r" \ +# RUN: -o exit | FileCheck %s --check-prefix=CHECK-DSYM + +# CHECK: (lldb) frame variable r +# CHECK-NEXT: (Request) ::r = (m_request = "Hello, World!") + +# CHECK-DSYM: (lldb) frame variable r +# CHECK-DSYM-NEXT: (Request) ::r = (m_request = "Hello, World!") + +#--- lib.h +#ifndef LIB_H_IN +#define LIB_H_IN + +#ifdef __OBJC__ +@class NSString; +#else +class NSString; +#endif + +struct Request { + NSString * m_request = nullptr; +}; + +#endif // _H_IN + +#--- main.cpp +#include "lib.h" + +void process(Request *); + +Request r; + +int main() { + process(&r); + return 0; +} + +#--- request.m +#import + +#include "lib.h" + +void process(Request * r) { + r->m_request = @"Hello, World!"; +} diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp index 97908b4acaf28..18d254e76b917 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp @@ -14,6 +14,12 @@ #include "DNBLog.h" #include #include +#include + +// From , but not on older OSs. +#ifndef VM_MEMORY_SANITIZER +#define VM_MEMORY_SANITIZER 99 +#endif MachVMRegion::MachVMRegion(task_t task) : m_task(task), m_addr(INVALID_NUB_ADDRESS), m_err(), diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 3f8201fa426fe..cb945b578e46a 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -180,28 +180,29 @@ if ("flang" IN_LIST LLVM_ENABLE_PROJECTS) endif() if ("libc" IN_LIST LLVM_ENABLE_PROJECTS) - message(WARNING "Using LLVM_ENABLE_PROJECTS=libc is deprecated. Please use " + message(WARNING "Using LLVM_ENABLE_PROJECTS=libc is deprecated now, and will " + "become a fatal error in a future release. Please use " "-DLLVM_ENABLE_RUNTIMES=libc or see the instructions at " "https://libc.llvm.org/ for building the runtimes.") endif() if ("compiler-rt" IN_LIST LLVM_ENABLE_PROJECTS) message(WARNING "Using LLVM_ENABLE_PROJECTS=compiler-rt is deprecated now, and will " - "become a fatal error in the LLVM 21 release. Please use " + "become a fatal error in a future release. Please use " "-DLLVM_ENABLE_RUNTIMES=compiler-rt or see the instructions at " "https://compiler-rt.llvm.org/ for building the runtimes.") endif() if ("offload" IN_LIST LLVM_ENABLE_PROJECTS) message(WARNING "Using LLVM_ENABLE_PROJECTS=offload is deprecated now, and will " - "become a fatal error in the LLVM 21 release. Please use " + "become a fatal error in a future release. Please use " "-DLLVM_ENABLE_RUNTIMES=offload or see the instructions at " "https://openmp.llvm.org/ for building the runtimes.") endif() if ("openmp" IN_LIST LLVM_ENABLE_PROJECTS) message(WARNING "Using LLVM_ENABLE_PROJECTS=openmp is deprecated now, and will " - "become a fatal error in the LLVM 21 release. Please use " + "become a fatal error in a future release. Please use " "-DLLVM_ENABLE_RUNTIMES=openmp or see the instructions at " "https://openmp.llvm.org/ for building the runtimes.") endif() @@ -214,7 +215,7 @@ endif () if ("libclc" IN_LIST LLVM_ENABLE_PROJECTS) message(WARNING "Using LLVM_ENABLE_PROJECTS=libclc is deprecated now, and will " - "become a fatal error in the LLVM 21 release. Please use " + "become a fatal error in a future release. Please use " "-DLLVM_ENABLE_RUNTIMES=libclc or see the instructions at " "https://libclc.llvm.org/ for building the runtimes.") endif() diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index c126b0d073322..c59911c52c625 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -797,6 +797,16 @@ if (MSVC) # Enable warnings if (LLVM_ENABLE_WARNINGS) + # Remove all -wd flag to enable warnings + if (NOT CLANG_CL) + set(msvc_warning_flags + # Promoted warnings. + -w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning. + + # Promoted warnings to errors. + -we4238 # Promote 'nonstandard extension used : class rvalue used as lvalue' to error. + ) + endif(NOT CLANG_CL) # Put /W4 in front of all the -we flags. cl.exe doesn't care, but for # clang-cl having /W4 after the -we flags will re-enable the warnings # disabled by -we. diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 8ea850af7a69b..2a9b67b671e11 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -413,6 +413,8 @@ added in the future: - On AArch64 the callee preserve all general purpose registers, except X0-X8 and X16-X18. Not allowed with ``nest``. + - On RISC-V the callee preserve x5-x31 except x6, x7 and x28 registers. + The idea behind this convention is to support calls to runtime functions that have a hot path and a cold path. The hot path is usually a small piece of code that doesn't use many registers. The cold path might need to call out to diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index 6191a915051fa..8e97f25ba5e40 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -154,10 +154,23 @@ Changes to the MIPS Backend --------------------------- * `-mcpu=i6400` and `-mcpu=i6500` were added. +* Added support for `mipsel-windows-gnu` and `mipsel-windows-msvc` targets. Changes to the PowerPC Backend ------------------------------ +* Add spill and restore for DMR and DMRp registers. +* Prototype various Dense Math Facility instructions, and intrinsics for basic enablement, insert/extract, integer and FP calculations. +* Add prototype for Dense Math Facility cryptography instructions. +* Implement load/stores prototype for v1024i1, v2048i1. +* Support conversion between f16 and f128. +* Change default for auto gen stxvp for cpu=future. +* Setup initial JITLink build support for XCOFF. +* Add an API to derive the default feature set from a CPU name within the TargetParser + (e.g. `pwr10` -> `+vsx`,`+isa3_1`,`+mma`). Clang now uses this to populate the `target-feature` + list when `-mcpu` is provided for PowerPC. +* Various bug fixes and codegen improvements. + Changes to the RISC-V Backend ----------------------------- @@ -219,6 +232,7 @@ Changes to the RISC-V Backend * Removed -mattr=+no-rvc-hints that could be used to disable parsing and generation of RVC hints. * Adds assembler support for the Andes `XAndesvsintload` (Andes Vector INT4 Load extension). * Adds assembler support for the Andes `XAndesbfhcvt` (Andes Scalar BFLOAT16 Conversion extension). +* Add combine for shadd family of instructions. Changes to the WebAssembly Backend ---------------------------------- @@ -228,11 +242,14 @@ Changes to the Windows Target * `fp128` is now passed indirectly, meaning it uses the same calling convention as `i128`. +* Added support for `mipsel-windows-gnu` and `mipsel-windows-msvc` targets. Changes to the X86 Backend -------------------------- * `fp128` will now use `*f128` libcalls on 32-bit GNU targets as well. +* On x86-32, `fp128` and `i128` are now passed with the expected 16-byte stack + alignment. Changes to the OCaml bindings ----------------------------- @@ -311,10 +328,21 @@ Changes to LLDB stop reason = SIGSEGV: sent by tkill system call (sender pid=649752, uid=2667987) ``` * ELF Cores can now have their siginfo structures inspected using `thread siginfo`. +* LLDB now uses + [DIL](https://discourse.llvm.org/t/rfc-data-inspection-language/69893) as the + default implementation for 'frame variable'. This should not change the + behavior of 'frame variable' at all, at this time. To revert to using the + old implementation use: `settings set target.experimental.use-DIL false`. * Disassembly of unknown instructions now produces `` instead of nothing at all * Changed the format of opcode bytes to match llvm-objdump when disassembling RISC-V code with `disassemble`'s `--byte` option. +* LLDB added native support for the Model Context Protocol (MCP). An MCP + server can be started with the `protocol-server start MCP` command. +* On AArch64 Linux, LLDB will now show the state of the `STORE_ONLY` field of + `mte_ctrl`. This will only be shown on hardware that has the + `FEAT_MTE_STORE_ONLY` architecture feature. + ### Changes to lldb-dap @@ -329,6 +357,18 @@ Changes to Sanitizers Other Changes ------------- +* A new ThinLTO backend has been added to implement the + [Integrated Distributed ThinLTO](https://llvm.org/docs/DTLTO.html) (DTLTO) + feature. This new backend delegates the ThinLTO backend compilation jobs to an + external process (the distributor), which in turn coordinates distribution + through a system such as Incredibuild. A JSON interface is used for + communication with the distributor. + ([#47468](https://github.com/llvm/llvm-project/issues/47468)). + +Changes to the Profile Runtime +--------------------- + +* On AIX, avoid using mmap when reading profile files from a non-local filesystem. External Open Source Projects Using LLVM {{env.config.release}} =============================================================== diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h index d92868e3715f4..33ad1db48716f 100644 --- a/llvm/include/llvm/ADT/FunctionExtras.h +++ b/llvm/include/llvm/ADT/FunctionExtras.h @@ -153,7 +153,7 @@ template class UniqueFunctionBase { void *StoragePtr; size_t Size; size_t Alignment; - } OutOfLineStorage; + } OutOfLineStorage = {}; static_assert( sizeof(OutOfLineStorageT) <= InlineStorageSize, "Should always use all of the out-of-line storage for inline storage!"); diff --git a/llvm/include/llvm/Analysis/IVDescriptors.h b/llvm/include/llvm/Analysis/IVDescriptors.h index b985292ccee40..1dc73205a0ebb 100644 --- a/llvm/include/llvm/Analysis/IVDescriptors.h +++ b/llvm/include/llvm/Analysis/IVDescriptors.h @@ -47,6 +47,8 @@ enum class RecurKind { FMul, ///< Product of floats. FMin, ///< FP min implemented in terms of select(cmp()). FMax, ///< FP max implemented in terms of select(cmp()). + FMinNum, ///< FP min with llvm.minnum semantics including NaNs. + FMaxNum, ///< FP max with llvm.maxnum semantics including NaNs. FMinimum, ///< FP min with llvm.minimum semantics FMaximum, ///< FP max with llvm.maximum semantics FMinimumNum, ///< FP min with llvm.minimumnum semantics @@ -250,6 +252,7 @@ class RecurrenceDescriptor { /// Returns true if the recurrence kind is a floating-point min/max kind. static bool isFPMinMaxRecurrenceKind(RecurKind Kind) { return Kind == RecurKind::FMin || Kind == RecurKind::FMax || + Kind == RecurKind::FMinNum || Kind == RecurKind::FMaxNum || Kind == RecurKind::FMinimum || Kind == RecurKind::FMaximum || Kind == RecurKind::FMinimumNum || Kind == RecurKind::FMaximumNum; } diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index ebb257ab33821..cfae75d093421 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -362,6 +362,7 @@ enum { ELFOSABI_FENIXOS = 16, // FenixOS ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI ELFOSABI_CUDA = 51, // NVIDIA CUDA architecture. + ELFOSABI_CUDA_V2 = 41, // NVIDIA CUDA architecture. ELFOSABI_FIRST_ARCH = 64, // First architecture-specific OS ABI ELFOSABI_AMDGPU_HSA = 64, // AMD HSA runtime ELFOSABI_AMDGPU_PAL = 65, // AMD PAL runtime @@ -385,6 +386,12 @@ enum { ELFABIVERSION_AMDGPU_HSA_V6 = 4, }; +// CUDA OS ABI Version identification. +enum { + ELFABIVERSION_CUDA_V1 = 7, + ELFABIVERSION_CUDA_V2 = 8, +}; + #define ELF_RELOC(name, value) name = value, // X86_64 relocations. @@ -921,9 +928,15 @@ enum { // NVPTX specific e_flags. enum : unsigned { - // Processor selection mask for EF_CUDA_SM* values. + // Processor selection mask for EF_CUDA_SM* values prior to blackwell. EF_CUDA_SM = 0xff, + // Processor selection mask for EF_CUDA_SM* values following blackwell. + EF_CUDA_SM_MASK = 0xff00, + + // Processor selection mask for EF_CUDA_SM* values following blackwell. + EF_CUDA_SM_OFFSET = 8, + // SM based processor values. EF_CUDA_SM20 = 0x14, EF_CUDA_SM21 = 0x15, @@ -943,9 +956,15 @@ enum : unsigned { EF_CUDA_SM80 = 0x50, EF_CUDA_SM86 = 0x56, EF_CUDA_SM87 = 0x57, + EF_CUDA_SM88 = 0x58, EF_CUDA_SM89 = 0x59, - // The sm_90a variant uses the same machine flag. EF_CUDA_SM90 = 0x5a, + EF_CUDA_SM100 = 0x64, + EF_CUDA_SM101 = 0x65, + EF_CUDA_SM103 = 0x67, + EF_CUDA_SM110 = 0x6e, + EF_CUDA_SM120 = 0x78, + EF_CUDA_SM121 = 0x79, // Unified texture binding is enabled. EF_CUDA_TEXMODE_UNIFIED = 0x100, @@ -954,12 +973,15 @@ enum : unsigned { // The target is using 64-bit addressing. EF_CUDA_64BIT_ADDRESS = 0x400, // Set when using the sm_90a processor. - EF_CUDA_ACCELERATORS = 0x800, + EF_CUDA_ACCELERATORS_V1 = 0x800, // Undocumented software feature. EF_CUDA_SW_FLAG_V2 = 0x1000, // Virtual processor selection mask for EF_CUDA_VIRTUAL_SM* values. EF_CUDA_VIRTUAL_SM = 0xff0000, + + // Set when using an accelerator variant like sm_100a. + EF_CUDA_ACCELERATORS = 0x8, }; // ELF Relocation types for BPF diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 938d71dd030e8..9e3d9196cc184 100644 --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -323,10 +323,11 @@ class MachineBasicBlock const MachineFunction *getParent() const { return xParent; } MachineFunction *getParent() { return xParent; } - /// Returns true if the original IR terminator is an `indirectbr`. This - /// typically corresponds to a `goto` in C, rather than jump tables. - bool terminatorIsComputedGoto() const { - return back().isIndirectBranch() && + /// Returns true if the original IR terminator is an `indirectbr` with + /// successor blocks. This typically corresponds to a `goto` in C, rather than + /// jump tables. + bool terminatorIsComputedGotoWithSuccessors() const { + return back().isIndirectBranch() && !succ_empty() && llvm::all_of(successors(), [](const MachineBasicBlock *Succ) { return Succ->isIRBlockAddressTaken(); }); diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h index 646588a2a92a5..9104e93ed9783 100644 --- a/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/llvm/include/llvm/CodeGen/MachineOperand.h @@ -788,6 +788,9 @@ class MachineOperand { LLVM_ABI void ChangeToBA(const BlockAddress *BA, int64_t Offset, unsigned TargetFlags = 0); + /// ChangeToCPI - Replace this operand with a new constant pool index operand. + LLVM_ABI void ChangeToCPI(unsigned Idx, int Offset, unsigned TargetFlags = 0); + /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. LLVM_ABI void ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags = 0); diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index b5b83c7ff1164..4d6e34bf4e3a1 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -1730,6 +1730,17 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo { return true; } + /// Return true if it's safe to move a machine instruction. + /// This allows the backend to prevent certain special instruction + /// sequences from being broken by instruction motion in optimization + /// passes. + /// By default, this returns true for every instruction. + virtual bool isSafeToMove(const MachineInstr &MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const { + return true; + } + /// Test if the given instruction should be considered a scheduling boundary. /// This primarily includes labels and terminators. virtual bool isSchedulingBoundary(const MachineInstr &MI, diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h index cdc80c88b7425..611bfe3f8aced 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -795,25 +795,9 @@ bool ConstructDecompositionT::applyClause( // assigned to which leaf constructs. // [5.2:340:33] - auto canMakePrivateCopy = [](llvm::omp::Clause id) { - switch (id) { - // Clauses with "privatization" property: - case llvm::omp::Clause::OMPC_firstprivate: - case llvm::omp::Clause::OMPC_in_reduction: - case llvm::omp::Clause::OMPC_lastprivate: - case llvm::omp::Clause::OMPC_linear: - case llvm::omp::Clause::OMPC_private: - case llvm::omp::Clause::OMPC_reduction: - case llvm::omp::Clause::OMPC_task_reduction: - return true; - default: - return false; - } - }; - bool applied = applyIf(node, [&](const auto &leaf) { return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { - return canMakePrivateCopy(n->id); + return llvm::omp::isPrivatizingClause(n->id); }); }); diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h index 35dafc6d246f0..d44c33301bde7 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h @@ -48,6 +48,22 @@ static constexpr inline bool canHaveIterator(Clause C) { } } +// Can clause C create a private copy of a variable. +static constexpr inline bool isPrivatizingClause(Clause C) { + switch (C) { + case OMPC_firstprivate: + case OMPC_in_reduction: + case OMPC_lastprivate: + case OMPC_linear: + case OMPC_private: + case OMPC_reduction: + case OMPC_task_reduction: + return true; + default: + return false; + } +} + static constexpr unsigned FallbackVersion = 52; LLVM_ABI ArrayRef getOpenMPVersions(); diff --git a/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h b/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h index 8aac9d5b49dbb..448a6e913eb86 100644 --- a/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h +++ b/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h @@ -135,6 +135,12 @@ template class GenericFloatingPointPredicateUtils { if (Mode.Input != DenormalMode::IEEE) return {Invalid, fcAllFlags, fcAllFlags}; + auto ExactClass = [IsFabs, Src](FPClassTest Mask) { + if (IsFabs) + Mask = llvm::inverse_fabs(Mask); + return exactClass(Src, Mask); + }; + switch (Pred) { case FCmpInst::FCMP_OEQ: // Match x == 0.0 return exactClass(Src, fcZero); @@ -151,26 +157,24 @@ template class GenericFloatingPointPredicateUtils { case FCmpInst::FCMP_UNO: return exactClass(Src, fcNan); case FCmpInst::FCMP_OGT: // x > 0 - return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf); + return ExactClass(fcPosSubnormal | fcPosNormal | fcPosInf); case FCmpInst::FCMP_UGT: // isnan(x) || x > 0 - return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan); + return ExactClass(fcPosSubnormal | fcPosNormal | fcPosInf | fcNan); case FCmpInst::FCMP_OGE: // x >= 0 - return exactClass(Src, fcPositive | fcNegZero); + return ExactClass(fcPositive | fcNegZero); case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0 - return exactClass(Src, fcPositive | fcNegZero | fcNan); + return ExactClass(fcPositive | fcNegZero | fcNan); case FCmpInst::FCMP_OLT: // x < 0 - return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf); + return ExactClass(fcNegSubnormal | fcNegNormal | fcNegInf); case FCmpInst::FCMP_ULT: // isnan(x) || x < 0 - return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan); + return ExactClass(fcNegSubnormal | fcNegNormal | fcNegInf | fcNan); case FCmpInst::FCMP_OLE: // x <= 0 - return exactClass(Src, fcNegative | fcPosZero); + return ExactClass(fcNegative | fcPosZero); case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0 - return exactClass(Src, fcNegative | fcPosZero | fcNan); + return ExactClass(fcNegative | fcPosZero | fcNan); default: llvm_unreachable("all compare types are handled"); } - - return {Invalid, fcAllFlags, fcAllFlags}; } const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass; diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index a6254eafa4906..9b081e9d65449 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -2120,7 +2120,7 @@ defvar X86CommonLibcalls = ); defvar Windows32DivRemMulCalls = - LibcallImpls<(add WindowsDivRemMulLibcalls), + LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL, RuntimeLibcallPredicate<"TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()">>; def X86_32SystemLibrary diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 5a8ec17dae1cc..22a493a8df013 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -489,6 +489,10 @@ class MCContext { /// \param Name - The symbol name, which must be unique across all symbols. LLVM_ABI MCSymbol *getOrCreateSymbol(const Twine &Name); + /// Variant of getOrCreateSymbol that handles backslash-escaped symbols. + /// For example, parse "a\"b\\" as a"\. + LLVM_ABI MCSymbol *parseSymbol(const Twine &Name); + /// Gets a symbol that will be defined to the final stack offset of a local /// variable after codegen. /// diff --git a/llvm/include/llvm/MC/MCDisassembler/MCDisassembler.h b/llvm/include/llvm/MC/MCDisassembler/MCDisassembler.h index 3a7ca1a69ab85..cae2fbcac1fef 100644 --- a/llvm/include/llvm/MC/MCDisassembler/MCDisassembler.h +++ b/llvm/include/llvm/MC/MCDisassembler/MCDisassembler.h @@ -136,6 +136,18 @@ class LLVM_ABI MCDisassembler { ArrayRef Bytes, uint64_t Address, raw_ostream &CStream) const = 0; + /// Returns the disassembly of an instruction bundle for VLIW architectures + /// like Hexagon. + /// + /// \param Instr - An MCInst to populate with the contents of + /// the Bundle with sub-instructions encoded as Inst operands. + virtual DecodeStatus getInstructionBundle(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &CStream) const { + return Fail; + } + /// Used to perform separate target specific disassembly for a particular /// symbol. May parse any prelude that precedes instructions after the /// start of a symbol, or the entire symbol. diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h index cb9bd5c600d52..e3f44a08db641 100644 --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -279,6 +279,9 @@ class LLVM_ABI MCAsmParser { /// Res to the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; + /// Parse identifier and get or create symbol for it. + bool parseSymbol(MCSymbol *&Res); + /// Parse up to the end of statement and return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 64b13972bfca1..9daaebf7e7935 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -298,8 +298,8 @@ class MCFragment { /// data. class MCEncodedFragment : public MCFragment { uint8_t BundlePadding = 0; - uint32_t ContentStart = 0; - uint32_t ContentEnd = 0; + uint32_t ContentSize = 0; + uint64_t ContentStart = 0; uint32_t FixupStart = 0; uint32_t FixupEnd = 0; @@ -360,22 +360,23 @@ class MCEncodedFragment : public MCFragment { // Content-related functions manage parent's storage using ContentStart and // ContentSize. - void clearContents() { ContentEnd = ContentStart; } + void clearContents() { ContentSize = 0; } // Get a SmallVector reference. The caller should call doneAppending to update - // `ContentEnd`. + // `ContentSize`. SmallVectorImpl &getContentsForAppending() { SmallVectorImpl &S = getParent()->ContentStorage; - if (LLVM_UNLIKELY(ContentEnd != S.size())) { + if (LLVM_UNLIKELY(ContentStart + ContentSize != S.size())) { // Move the elements to the end. Reserve space to avoid invalidating // S.begin()+I for `append`. - auto Size = ContentEnd - ContentStart; auto I = std::exchange(ContentStart, S.size()); - S.reserve(S.size() + Size); - S.append(S.begin() + I, S.begin() + I + Size); + S.reserve(S.size() + ContentSize); + S.append(S.begin() + I, S.begin() + I + ContentSize); } return S; } - void doneAppending() { ContentEnd = getParent()->ContentStorage.size(); } + void doneAppending() { + ContentSize = getParent()->ContentStorage.size() - ContentStart; + } void appendContents(ArrayRef Contents) { getContentsForAppending().append(Contents.begin(), Contents.end()); doneAppending(); @@ -387,11 +388,11 @@ class MCEncodedFragment : public MCFragment { LLVM_ABI void setContents(ArrayRef Contents); MutableArrayRef getContents() { return MutableArrayRef(getParent()->ContentStorage) - .slice(ContentStart, ContentEnd - ContentStart); + .slice(ContentStart, ContentSize); } ArrayRef getContents() const { return ArrayRef(getParent()->ContentStorage) - .slice(ContentStart, ContentEnd - ContentStart); + .slice(ContentStart, ContentSize); } // Fixup-related functions manage parent's storage using FixupStart and @@ -409,7 +410,7 @@ class MCEncodedFragment : public MCFragment { .slice(FixupStart, FixupEnd - FixupStart); } - size_t getSize() const { return ContentEnd - ContentStart; } + size_t getSize() const { return ContentSize; } }; /// Fragment for data and encoded instructions. diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 103686884e705..30a9dd35f624e 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -1479,6 +1479,7 @@ template Triple::OSType ELFObjectFile::getOS() const { case ELF::ELFOSABI_OPENBSD: return Triple::OpenBSD; case ELF::ELFOSABI_CUDA: + case ELF::ELFOSABI_CUDA_V2: return Triple::CUDA; case ELF::ELFOSABI_AMDGPU_HSA: return Triple::AMDHSA; diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp index 39f74beca082f..8be5de3bf356f 100644 --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -941,10 +941,30 @@ RecurrenceDescriptor::InstDesc RecurrenceDescriptor::isRecurrenceInstr( m_Intrinsic(m_Value(), m_Value())) || match(I, m_Intrinsic(m_Value(), m_Value())); }; - if (isIntMinMaxRecurrenceKind(Kind) || - (HasRequiredFMF() && isFPMinMaxRecurrenceKind(Kind))) + if (isIntMinMaxRecurrenceKind(Kind)) return isMinMaxPattern(I, Kind, Prev); - else if (isFMulAddIntrinsic(I)) + if (isFPMinMaxRecurrenceKind(Kind)) { + InstDesc Res = isMinMaxPattern(I, Kind, Prev); + if (!Res.isRecurrence()) + return InstDesc(false, I); + if (HasRequiredFMF()) + return Res; + // We may be able to vectorize FMax/FMin reductions using maxnum/minnum + // intrinsics with extra checks ensuring the vector loop handles only + // non-NaN inputs. + if (match(I, m_Intrinsic(m_Value(), m_Value()))) { + assert(Kind == RecurKind::FMax && + "unexpected recurrence kind for maxnum"); + return InstDesc(I, RecurKind::FMaxNum); + } + if (match(I, m_Intrinsic(m_Value(), m_Value()))) { + assert(Kind == RecurKind::FMin && + "unexpected recurrence kind for minnum"); + return InstDesc(I, RecurKind::FMinNum); + } + return InstDesc(false, I); + } + if (isFMulAddIntrinsic(I)) return InstDesc(Kind == RecurKind::FMulAdd, I, I->hasAllowReassoc() ? nullptr : I); return InstDesc(false, I); diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 393f2648de3c9..fcc2cf2f7e8e7 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -382,7 +382,10 @@ bool llvm::isDereferenceableAndAlignedInLoop( if (Offset->getAPInt().urem(Alignment.value()) != 0) return false; - AccessSize = MaxPtrDiff + Offset->getAPInt(); + bool Overflow = false; + AccessSize = MaxPtrDiff.uadd_ov(Offset->getAPInt(), Overflow); + if (Overflow) + return false; AccessSizeSCEV = SE.getAddExpr(PtrDiff, Offset); Base = NewBase->getValue(); } else diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 24adfa346c642..221468a2d1a84 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -15093,15 +15093,20 @@ void SCEVUnionPredicate::add(const SCEVPredicate *N, ScalarEvolution &SE) { return; } + // Implication checks are quadratic in the number of predicates. Stop doing + // them if there are many predicates, as they should be too expensive to use + // anyway at that point. + bool CheckImplies = Preds.size() < 16; + // Only add predicate if it is not already implied by this union predicate. - if (implies(N, SE)) + if (CheckImplies && implies(N, SE)) return; // Build a new vector containing the current predicates, except the ones that // are implied by the new predicate N. SmallVector PrunedPreds; for (auto *P : Preds) { - if (N->implies(P, SE)) + if (CheckImplies && N->implies(P, SE)) continue; PrunedPreds.push_back(P); } diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp index 3b3e7a418feb5..f32a18833d162 100644 --- a/llvm/lib/CodeGen/BranchFolding.cpp +++ b/llvm/lib/CodeGen/BranchFolding.cpp @@ -1971,6 +1971,7 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) { MachineBasicBlock::iterator FIB = FBB->begin(); MachineBasicBlock::iterator TIE = TBB->end(); MachineBasicBlock::iterator FIE = FBB->end(); + MachineFunction &MF = *TBB->getParent(); while (TIB != TIE && FIB != FIE) { // Skip dbg_value instructions. These do not count. TIB = skipDebugInstructionsForward(TIB, TIE, false); @@ -1985,6 +1986,10 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) { // Hard to reason about register liveness with predicated instruction. break; + if (!TII->isSafeToMove(*TIB, TBB, MF)) + // Don't hoist the instruction if it isn't safe to move. + break; + bool IsSafe = true; for (MachineOperand &MO : TIB->operands()) { // Don't attempt to hoist instructions with register masks. diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 9bbb89e37865d..3d1408256df8e 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2096,6 +2096,10 @@ static bool isRemOfLoopIncrementWithLoopInvariant( if (!L->isLoopInvariant(RemAmt)) return false; + // Only works if the AddOffset is a loop invaraint + if (AddOffset && !L->isLoopInvariant(AddOffset)) + return false; + // Is the PHI a loop increment? auto LoopIncrInfo = getIVIncrement(PN, LI); if (!LoopIncrInfo) diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp index 742de1101faa2..620767a39b912 100644 --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -937,16 +937,6 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { if (CopyOperands) { Register RegSrc = CopyOperands->Source->getReg(); Register RegDef = CopyOperands->Destination->getReg(); - // It's possible that the previous transformations have resulted in a - // no-op register move (i.e. one where source and destination registers - // are the same and are not referring to a reserved register). If so, - // delete it. - if (RegSrc == RegDef && !MRI->isReserved(RegSrc)) { - MI.eraseFromParent(); - NumDeletes++; - Changed = true; - continue; - } if (!TRI->regsOverlap(RegDef, RegSrc)) { // Copy is now a candidate for deletion. diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp index 0d251697f2567..f09855c43af60 100644 --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -218,6 +218,19 @@ void MachineOperand::ChangeToBA(const BlockAddress *BA, int64_t Offset, setTargetFlags(TargetFlags); } +void MachineOperand::ChangeToCPI(unsigned Idx, int Offset, + unsigned TargetFlags) { + assert((!isReg() || !isTied()) && + "Cannot change a tied operand into a constant pool index"); + + removeRegFromUses(); + + OpKind = MO_ConstantPoolIndex; + setIndex(Idx); + setOffset(Offset); + setTargetFlags(TargetFlags); +} + void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) { assert((!isReg() || !isTied()) && "Cannot change a tied operand into an MCSymbol"); diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp index b38a4d1c55af9..0e7cb0c980d40 100644 --- a/llvm/lib/CodeGen/MachinePipeliner.cpp +++ b/llvm/lib/CodeGen/MachinePipeliner.cpp @@ -110,6 +110,7 @@ STATISTIC(NumFailZeroMII, "Pipeliner abort due to zero MII"); STATISTIC(NumFailNoSchedule, "Pipeliner abort due to no schedule found"); STATISTIC(NumFailZeroStage, "Pipeliner abort due to zero stage"); STATISTIC(NumFailLargeMaxStage, "Pipeliner abort due to too many stages"); +STATISTIC(NumFailTooManyStores, "Pipeliner abort due to too many stores"); /// A command line option to turn software pipelining on or off. static cl::opt EnableSWP("enable-pipeliner", cl::Hidden, cl::init(true), @@ -193,6 +194,13 @@ static cl::opt MVECodeGen("pipeliner-mve-cg", cl::Hidden, cl::init(false), cl::desc("Use the MVE code generator for software pipelining")); +/// A command line argument to limit the number of store instructions in the +/// target basic block. +static cl::opt SwpMaxNumStores( + "pipeliner-max-num-stores", + cl::desc("Maximum number of stores allwed in the target loop."), cl::Hidden, + cl::init(200)); + namespace llvm { // A command line option to enable the CopyToPhi DAG mutation. @@ -544,6 +552,23 @@ bool MachinePipeliner::canPipelineLoop(MachineLoop &L) { return false; } + unsigned NumStores = 0; + for (MachineInstr &MI : *L.getHeader()) + if (MI.mayStore()) + ++NumStores; + if (NumStores > SwpMaxNumStores) { + LLVM_DEBUG(dbgs() << "Too many stores\n"); + NumFailTooManyStores++; + ORE->emit([&]() { + return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "canPipelineLoop", + L.getStartLoc(), L.getHeader()) + << "Too many store instructions in the loop: " + << ore::NV("NumStores", NumStores) << " > " + << ore::NV("SwpMaxNumStores", SwpMaxNumStores) << "."; + }); + return false; + } + // Remove any subregisters from inputs to phi nodes. preprocessPhiNodes(*L.getHeader()); return true; @@ -4279,8 +4304,8 @@ void LoopCarriedEdges::modifySUnits(std::vector &SUnits, !TII->isGlobalMemoryObject(FromMI) && !TII->isGlobalMemoryObject(ToMI) && !isSuccOrder(From, To)) { SDep Pred = Dep; - Pred.setSUnit(Src); - Dst->addPred(Pred); + Pred.setSUnit(From); + To->addPred(Pred); } } } diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 8de2c48581a1e..9fa96e7372961 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -587,12 +587,14 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const { break; case Intrinsic::exp: case Intrinsic::exp2: + case Intrinsic::log: Changed |= forEachCall(F, [&](CallInst *CI) { Type *Ty = CI->getArgOperand(0)->getType(); if (!isa(Ty)) return false; const TargetLowering *TL = TM->getSubtargetImpl(F)->getTargetLowering(); unsigned Op = TL->IntrinsicIDToISD(F.getIntrinsicID()); + assert(Op != ISD::DELETED_NODE && "unsupported intrinsic"); if (!TL->isOperationExpand(Op, EVT::getEVT(Ty))) return false; return lowerUnaryVectorIntrinsicAsLoop(M, CI); diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 13ed8f28d5507..2052e9a75d89b 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -502,7 +502,7 @@ static Value *getTrueOrFalseValue( } else { assert((isa(AuxI) || isa(AuxI)) && "Unexpected opcode"); - CBO->setOperand(CondIdx, ConstantInt::get(CBO->getType(), -1)); + CBO->setOperand(CondIdx, ConstantInt::getAllOnesValue(CBO->getType())); } unsigned OtherIdx = 1 - CondIdx; diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 23812d795f5fa..91fd2d843f445 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -16717,7 +16717,8 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) { // Fold freeze(op(x, ...)) -> op(freeze(x), ...). // Try to push freeze through instructions that propagate but don't produce // poison as far as possible. If an operand of freeze follows three - // conditions 1) one-use, and 2) does not produce poison then push + // conditions 1) one-use, 2) does not produce poison, and 3) has all but one + // guaranteed-non-poison operands (or is a BUILD_VECTOR or similar) then push // the freeze through to the operands that are not guaranteed non-poison. // NOTE: we will strip poison-generating flags, so ignore them here. if (DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false, @@ -16725,6 +16726,18 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) { N0->getNumValues() != 1 || !N0->hasOneUse()) return SDValue(); + // TOOD: we should always allow multiple operands, however this increases the + // likelihood of infinite loops due to the ReplaceAllUsesOfValueWith call + // below causing later nodes that share frozen operands to fold again and no + // longer being able to confirm other operands are not poison due to recursion + // depth limits on isGuaranteedNotToBeUndefOrPoison. + bool AllowMultipleMaybePoisonOperands = + N0.getOpcode() == ISD::SELECT_CC || N0.getOpcode() == ISD::SETCC || + N0.getOpcode() == ISD::BUILD_VECTOR || + N0.getOpcode() == ISD::BUILD_PAIR || + N0.getOpcode() == ISD::VECTOR_SHUFFLE || + N0.getOpcode() == ISD::CONCAT_VECTORS || N0.getOpcode() == ISD::FMUL; + // Avoid turning a BUILD_VECTOR that can be recognized as "all zeros", "all // ones" or "constant" into something that depends on FrozenUndef. We can // instead pick undef values to keep those properties, while at the same time @@ -16757,6 +16770,10 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) { MaybePoisonOperandNumbers.push_back(OpNo); if (!HadMaybePoisonOperands) continue; + if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) { + // Multiple maybe-poison ops when not allowed - bail out. + return SDValue(); + } } // NOTE: the whole op may be not guaranteed to not be undef or poison because // it could create undef or poison due to it's poison-generating flags. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index 2cad36eff9c88..fe357106bda60 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -1551,6 +1551,7 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break; case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break; + case ISD::AssertNoFPClass: ExpandFloatRes_AssertNoFPClass(N, Lo, Hi); break; case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break; case ISD::STRICT_FMINNUM: case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break; @@ -1966,6 +1967,13 @@ void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi); } +void DAGTypeLegalizer::ExpandFloatRes_AssertNoFPClass(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // TODO: Handle ppcf128 by preserving AssertNoFPClass for one of the halves. + SDLoc dl(N); + GetExpandedFloat(N->getOperand(0), Lo, Hi); +} + void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 9b537248d4ab4..4eaa79890e005 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -677,6 +677,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { SDNode *N, RTLIB::Libcall LC, std::optional CallRetResNo = {}); // clang-format off + void ExpandFloatRes_AssertNoFPClass(SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FABS (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FACOS (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FASIN (SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/llvm/lib/CodeGen/TailDuplicator.cpp b/llvm/lib/CodeGen/TailDuplicator.cpp index a88c57fdc165a..8cbdadd979810 100644 --- a/llvm/lib/CodeGen/TailDuplicator.cpp +++ b/llvm/lib/CodeGen/TailDuplicator.cpp @@ -604,12 +604,23 @@ bool TailDuplicator::shouldTailDuplicate(bool IsSimple, bool HasComputedGoto = false; if (!TailBB.empty()) { HasIndirectbr = TailBB.back().isIndirectBranch(); - HasComputedGoto = TailBB.terminatorIsComputedGoto(); + HasComputedGoto = TailBB.terminatorIsComputedGotoWithSuccessors(); } if (HasIndirectbr && PreRegAlloc) MaxDuplicateCount = TailDupIndirectBranchSize; + // Allow higher limits when the block has computed-gotos and running after + // register allocation. NB. This basically unfactors computed gotos that were + // factored early on in the compilation process to speed up edge based data + // flow. If we do not unfactor them again, it can seriously pessimize code + // with many computed jumps in the source code, such as interpreters. + // Therefore we do not restrict the computed gotos. + bool DupComputedGotoLate = + HasComputedGoto && MF->getTarget().getTargetTriple().isOSDarwin(); + if (DupComputedGotoLate && !PreRegAlloc) + MaxDuplicateCount = std::max(MaxDuplicateCount, 10u); + // Check the instructions in the block to determine whether tail-duplication // is invalid or unlikely to be profitable. unsigned InstrCount = 0; @@ -663,12 +674,10 @@ bool TailDuplicator::shouldTailDuplicate(bool IsSimple, // Duplicating a BB which has both multiple predecessors and successors will // may cause huge amount of PHI nodes. If we want to remove this limitation, // we have to address https://github.com/llvm/llvm-project/issues/78578. - // NB. This basically unfactors computed gotos that were factored early on in - // the compilation process to speed up edge based data flow. If we do not - // unfactor them again, it can seriously pessimize code with many computed - // jumps in the source code, such as interpreters. Therefore we do not - // restrict the computed gotos. - if (!HasComputedGoto && TailBB.pred_size() > TailDupPredSize && + bool CheckSuccessorAndPredecessorSize = + DupComputedGotoLate ? PreRegAlloc : !HasComputedGoto; + if (CheckSuccessorAndPredecessorSize && + TailBB.pred_size() > TailDupPredSize && TailBB.succ_size() > TailDupSuccSize) { // If TailBB or any of its successors contains a phi, we may have to add a // large number of additional phis with additional incoming values. diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 6feeb19bb8589..ca2a57e9b7b2c 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -806,7 +806,17 @@ void TargetLoweringBase::initActions() { ISD::SDIVFIX, ISD::SDIVFIXSAT, ISD::UDIVFIX, ISD::UDIVFIXSAT, ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT, - ISD::IS_FPCLASS}, + ISD::IS_FPCLASS, ISD::FCBRT, + ISD::FLOG, ISD::FLOG2, + ISD::FLOG10, ISD::FEXP, + ISD::FEXP2, ISD::FEXP10, + ISD::FFLOOR, ISD::FNEARBYINT, + ISD::FCEIL, ISD::FRINT, + ISD::FTRUNC, ISD::FROUNDEVEN, + ISD::FTAN, ISD::FACOS, + ISD::FASIN, ISD::FATAN, + ISD::FCOSH, ISD::FSINH, + ISD::FTANH, ISD::FATAN2}, VT, Expand); // Overflow operations default to expand @@ -852,13 +862,12 @@ void TargetLoweringBase::initActions() { // These operations default to expand for vector types. if (VT.isVector()) - setOperationAction( - {ISD::FCOPYSIGN, ISD::SIGN_EXTEND_INREG, ISD::ANY_EXTEND_VECTOR_INREG, - ISD::SIGN_EXTEND_VECTOR_INREG, ISD::ZERO_EXTEND_VECTOR_INREG, - ISD::SPLAT_VECTOR, ISD::LRINT, ISD::LLRINT, ISD::LROUND, - ISD::LLROUND, ISD::FTAN, ISD::FACOS, ISD::FASIN, ISD::FATAN, - ISD::FCOSH, ISD::FSINH, ISD::FTANH, ISD::FATAN2}, - VT, Expand); + setOperationAction({ISD::FCOPYSIGN, ISD::SIGN_EXTEND_INREG, + ISD::ANY_EXTEND_VECTOR_INREG, + ISD::SIGN_EXTEND_VECTOR_INREG, + ISD::ZERO_EXTEND_VECTOR_INREG, ISD::SPLAT_VECTOR, + ISD::LRINT, ISD::LLRINT, ISD::LROUND, ISD::LLROUND}, + VT, Expand); // Constrained floating-point operations default to expand. #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ @@ -914,15 +923,6 @@ void TargetLoweringBase::initActions() { {MVT::bf16, MVT::f16, MVT::f32, MVT::f64, MVT::f80, MVT::f128}, Expand); - // These library functions default to expand. - setOperationAction({ISD::FCBRT, ISD::FLOG, ISD::FLOG2, ISD::FLOG10, - ISD::FEXP, ISD::FEXP2, ISD::FEXP10, ISD::FFLOOR, - ISD::FNEARBYINT, ISD::FCEIL, ISD::FRINT, ISD::FTRUNC, - ISD::FROUNDEVEN, ISD::FTAN, ISD::FACOS, ISD::FASIN, - ISD::FATAN, ISD::FCOSH, ISD::FSINH, ISD::FTANH, - ISD::FATAN2}, - {MVT::f32, MVT::f64, MVT::f128}, Expand); - // Insert custom handling default for llvm.canonicalize.*. setOperationAction(ISD::FCANONICALIZE, {MVT::f16, MVT::f32, MVT::f64, MVT::f128}, Expand); @@ -1922,6 +1922,8 @@ int TargetLoweringBase::IntrinsicIDToISD(Intrinsic::ID ID) const { return ISD::FEXP; case Intrinsic::exp2: return ISD::FEXP2; + case Intrinsic::log: + return ISD::FLOG; default: return ISD::DELETED_NODE; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 8ec3f1729b974..04f5fc0ebae67 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -1444,8 +1444,8 @@ void DWARFVerifier::verifyNameIndexAttribute( } if (AttrEnc.Index == dwarf::DW_IDX_parent) { - constexpr static auto AllowedForms = {dwarf::Form::DW_FORM_flag_present, - dwarf::Form::DW_FORM_ref4}; + static constexpr dwarf::Form AllowedForms[] = { + dwarf::Form::DW_FORM_flag_present, dwarf::Form::DW_FORM_ref4}; if (!is_contained(AllowedForms, AttrEnc.Form)) { ErrorCategory.Report("Unexpected NameIndex Abbreviation", [&]() { error() << formatv( diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 8004077b92665..9afbefb8c08ef 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3185,12 +3185,6 @@ void Verifier::visitFunction(const Function &F) { CheckDI(SP->describes(&F), "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); - - if (DL->getAtomGroup()) - CheckDI(DL->getScope()->getSubprogram()->getKeyInstructionsEnabled(), - "DbgLoc uses atomGroup but DISubprogram doesn't have Key " - "Instructions enabled", - DL, DL->getScope()->getSubprogram()); }; for (auto &BB : F) for (auto &I : BB) { @@ -5492,6 +5486,15 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *N = I.getDebugLoc().getAsMDNode()) { CheckDI(isa(N), "invalid !dbg metadata attachment", &I, N); visitMDNode(*N, AreDebugLocsAllowed::Yes); + + if (auto *DL = dyn_cast(N)) { + if (DL->getAtomGroup()) { + CheckDI(DL->getScope()->getSubprogram()->getKeyInstructionsEnabled(), + "DbgLoc uses atomGroup but DISubprogram doesn't have Key " + "Instructions enabled", + DL, DL->getScope()->getSubprogram()); + } + } } if (auto *DII = dyn_cast(&I)) { diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 890184db1d1ef..1625455e38e06 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -217,27 +217,6 @@ MCDataFragment *MCContext::allocInitialFragment(MCSection &Sec) { MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) { SmallString<128> NameSV; StringRef NameRef = Name.toStringRef(NameSV); - if (NameRef.contains('\\')) { - NameSV = NameRef; - size_t S = 0; - // Support escaped \\ and \" as in GNU Assembler. GAS issues a warning for - // other characters following \\, which we do not implement due to code - // structure. - for (size_t I = 0, E = NameSV.size(); I != E; ++I) { - char C = NameSV[I]; - if (C == '\\' && I + 1 != E) { - switch (NameSV[I + 1]) { - case '"': - case '\\': - C = NameSV[++I]; - break; - } - } - NameSV[S++] = C; - } - NameSV.resize(S); - NameRef = NameSV; - } assert(!NameRef.empty() && "Normal symbols cannot be unnamed!"); @@ -258,6 +237,34 @@ MCSymbol *MCContext::getOrCreateSymbol(const Twine &Name) { return Entry.second.Symbol; } +MCSymbol *MCContext::parseSymbol(const Twine &Name) { + SmallString<128> SV; + StringRef NameRef = Name.toStringRef(SV); + if (NameRef.contains('\\')) { + SV = NameRef; + size_t S = 0; + // Support escaped \\ and \" as in GNU Assembler. GAS issues a warning for + // other characters following \\, which we do not implement due to code + // structure. + for (size_t I = 0, E = SV.size(); I != E; ++I) { + char C = SV[I]; + if (C == '\\' && I + 1 != E) { + switch (SV[I + 1]) { + case '"': + case '\\': + C = SV[++I]; + break; + } + } + SV[S++] = C; + } + SV.resize(S); + NameRef = SV; + } + + return getOrCreateSymbol(NameRef); +} + MCSymbol *MCContext::getOrCreateFrameAllocSymbol(const Twine &FuncName, unsigned Idx) { return getOrCreateSymbol(MAI->getPrivateGlobalPrefix() + FuncName + diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index a196591744099..a877eb7938ebf 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -361,6 +361,9 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, if (BBeforeRelax && AAfterRelax) return; } + const auto *RF = dyn_cast(F); + if (RF && RF->isLinkerRelaxable()) + return; if (&*F == FA) { // If FA and FB belong to the same subsection, the loop will find FA and // we can resolve the difference. diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index c59fabe5df1b9..28cddb9396467 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -70,6 +70,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << "\n Fixup @" << F.getOffset() << " Value:"; F.getValue()->print(OS, nullptr); OS << " Kind:" << F.getKind(); + if (F.isLinkerRelaxable()) + OS << " LinkerRelaxable"; } }; @@ -113,6 +115,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { } case MCFragment::FT_Relaxable: { const auto *F = cast(this); + if (F->isLinkerRelaxable()) + OS << " LinkerRelaxable"; OS << " Size:" << F->getContents().size() << ' '; F->getInst().dump_pretty(OS); printFixups(F->getFixups()); diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 44a82f75576b6..d9c39bbedf37c 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -408,6 +408,13 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, Inst, IF->getContentsForAppending(), Fixups, STI); IF->doneAppending(); IF->appendFixups(Fixups); + + for (auto &Fixup : Fixups) { + if (Fixup.isLinkerRelaxable()) { + IF->setLinkerRelaxable(); + getCurrentSectionOnly()->setLinkerRelaxable(); + } + } } #ifndef NDEBUG diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9fd6c05a846db..929051c4f0c17 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -1222,8 +1222,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); if (!Sym) - Sym = getContext().getOrCreateSymbol(MAI.isHLASM() ? SymbolName.upper() - : SymbolName); + Sym = getContext().parseSymbol(MAI.isHLASM() ? SymbolName.upper() + : SymbolName); // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. @@ -1854,7 +1854,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, RewrittenLabel); IDVal = RewrittenLabel; } - Sym = getContext().getOrCreateSymbol(IDVal); + Sym = getContext().parseSymbol(IDVal); } else Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); // End of Labels should be treated as end of line for lexing @@ -3897,20 +3897,15 @@ bool AsmParser::parseDirectiveCVLoc() { /// ::= .cv_linetable FunctionId, FnStart, FnEnd bool AsmParser::parseDirectiveCVLinetable() { int64_t FunctionId; - StringRef FnStartName, FnEndName; + MCSymbol *FnStartSym, *FnEndSym; SMLoc Loc = getTok().getLoc(); if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseComma() || parseTokenLoc(Loc) || - check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || + check(parseSymbol(FnStartSym), Loc, "expected identifier in directive") || parseComma() || parseTokenLoc(Loc) || - check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) + check(parseSymbol(FnEndSym), Loc, "expected identifier in directive")) return true; - MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); - MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); - getStreamer().emitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym); return false; } @@ -3919,7 +3914,7 @@ bool AsmParser::parseDirectiveCVLinetable() { /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd bool AsmParser::parseDirectiveCVInlineLinetable() { int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; - StringRef FnStartName, FnEndName; + MCSymbol *FnStartSym, *FnEndSym; SMLoc Loc = getTok().getLoc(); if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || parseTokenLoc(Loc) || @@ -3929,16 +3924,14 @@ bool AsmParser::parseDirectiveCVInlineLinetable() { parseIntToken(SourceLineNum, "expected SourceLineNum") || check(SourceLineNum < 0, Loc, "Line number less than zero") || parseTokenLoc(Loc) || - check(parseIdentifier(FnStartName), Loc, "expected identifier") || + check(parseSymbol(FnStartSym), Loc, "expected identifier") || parseTokenLoc(Loc) || - check(parseIdentifier(FnEndName), Loc, "expected identifier")) + check(parseSymbol(FnEndSym), Loc, "expected identifier")) return true; if (parseEOL()) return true; - MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); - MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); getStreamer().emitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); @@ -3959,16 +3952,14 @@ bool AsmParser::parseDirectiveCVDefRange() { std::vector> Ranges; while (getLexer().is(AsmToken::Identifier)) { Loc = getLexer().getLoc(); - StringRef GapStartName; - if (parseIdentifier(GapStartName)) + MCSymbol *GapStartSym; + if (parseSymbol(GapStartSym)) return Error(Loc, "expected identifier in directive"); - MCSymbol *GapStartSym = getContext().getOrCreateSymbol(GapStartName); Loc = getLexer().getLoc(); - StringRef GapEndName; - if (parseIdentifier(GapEndName)) + MCSymbol *GapEndSym; + if (parseSymbol(GapEndSym)) return Error(Loc, "expected identifier in directive"); - MCSymbol *GapEndSym = getContext().getOrCreateSymbol(GapEndName); Ranges.push_back({GapStartSym, GapEndSym}); } @@ -4105,12 +4096,11 @@ bool AsmParser::parseDirectiveCVFileChecksumOffset() { /// ::= .cv_fpo_data procsym bool AsmParser::parseDirectiveCVFPOData() { SMLoc DirLoc = getLexer().getLoc(); - StringRef ProcName; - if (parseIdentifier(ProcName)) + MCSymbol *ProcSym; + if (parseSymbol(ProcSym)) return TokError("expected symbol name"); if (parseEOL()) return true; - MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName); getStreamer().emitCVFPOData(ProcSym, DirLoc); return false; } @@ -4329,15 +4319,12 @@ bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { if (Encoding == dwarf::DW_EH_PE_omit) return false; - StringRef Name; + MCSymbol *Sym; if (check(!isValidEncoding(Encoding), "unsupported encoding.") || parseComma() || - check(parseIdentifier(Name), "expected identifier in directive") || - parseEOL()) + check(parseSymbol(Sym), "expected identifier in directive") || parseEOL()) return true; - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (IsPersonality) getStreamer().emitCFIPersonality(Sym, Encoding); else @@ -4966,7 +4953,7 @@ bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (discardLTOSymbol(Name)) return false; - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + MCSymbol *Sym = getContext().parseSymbol(Name); // Assembler local symbols don't make any sense here, except for directives // that the symbol should be tagged. @@ -4988,13 +4975,10 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) { return true; SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (parseIdentifier(Name)) + MCSymbol *Sym; + if (parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (parseComma()) return true; @@ -5827,10 +5811,9 @@ bool AsmParser::parseDirectiveAddrsig() { } bool AsmParser::parseDirectiveAddrsigSym() { - StringRef Name; - if (check(parseIdentifier(Name), "expected identifier") || parseEOL()) + MCSymbol *Sym; + if (check(parseSymbol(Sym), "expected identifier") || parseEOL()) return true; - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); getStreamer().emitAddrsigSym(Sym); return false; } @@ -6230,7 +6213,7 @@ bool HLASMAsmParser::parseAsHLASMLabel(ParseStatementInfo &Info, return Error(LabelLoc, "Cannot have just a label for an HLASM inline asm statement"); - MCSymbol *Sym = getContext().getOrCreateSymbol( + MCSymbol *Sym = getContext().parseSymbol( getContext().getAsmInfo()->isHLASM() ? LabelVal.upper() : LabelVal); // Emit the label. @@ -6357,7 +6340,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc); return false; } else - Sym = Parser.getContext().getOrCreateSymbol(Name); + Sym = Parser.getContext().parseSymbol(Name); Sym->setRedefinable(allow_redef); diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp index 9fb17488a9e9c..5dd79946d8779 100644 --- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -293,13 +293,11 @@ bool COFFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); if (getLexer().isNot(AsmToken::EndOfStatement)) { while (true) { - StringRef Name; + MCSymbol *Sym; - if (getParser().parseIdentifier(Name)) + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().emitSymbolAttribute(Sym, Attr); if (getLexer().is(AsmToken::EndOfStatement)) @@ -450,13 +448,11 @@ bool COFFAsmParser::parseDirectivePopSection(StringRef, SMLoc) { } bool COFFAsmParser::parseDirectiveDef(StringRef, SMLoc) { - StringRef SymbolName; + MCSymbol *Sym; - if (getParser().parseIdentifier(SymbolName)) + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); - getStreamer().beginCOFFSymbolDef(Sym); Lex(); @@ -496,8 +492,8 @@ bool COFFAsmParser::parseDirectiveEndef(StringRef, SMLoc) { } bool COFFAsmParser::parseDirectiveSecRel32(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); int64_t Offset = 0; @@ -517,8 +513,6 @@ bool COFFAsmParser::parseDirectiveSecRel32(StringRef, SMLoc) { "invalid '.secrel32' directive offset, can't be less " "than zero or greater than std::numeric_limits::max()"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSecRel32(Symbol, Offset); return false; @@ -526,8 +520,8 @@ bool COFFAsmParser::parseDirectiveSecRel32(StringRef, SMLoc) { bool COFFAsmParser::parseDirectiveRVA(StringRef, SMLoc) { auto parseOp = [&]() -> bool { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); int64_t Offset = 0; @@ -544,8 +538,6 @@ bool COFFAsmParser::parseDirectiveRVA(StringRef, SMLoc) { "than -2147483648 or greater than " "2147483647"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - getStreamer().emitCOFFImgRel32(Symbol, Offset); return false; }; @@ -556,75 +548,65 @@ bool COFFAsmParser::parseDirectiveRVA(StringRef, SMLoc) { } bool COFFAsmParser::parseDirectiveSafeSEH(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSafeSEH(Symbol); return false; } bool COFFAsmParser::parseDirectiveSecIdx(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSectionIndex(Symbol); return false; } bool COFFAsmParser::parseDirectiveSymIdx(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSymbolIndex(Symbol); return false; } bool COFFAsmParser::parseDirectiveSecNum(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSecNumber(Symbol); return false; } bool COFFAsmParser::parseDirectiveSecOffset(StringRef, SMLoc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return TokError("expected identifier in directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitCOFFSecOffset(Symbol); return false; @@ -679,15 +661,13 @@ bool COFFAsmParser::parseDirectiveLinkOnce(StringRef, SMLoc Loc) { } bool COFFAsmParser::parseSEHDirectiveStartProc(StringRef, SMLoc Loc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *Symbol; + if (getParser().parseSymbol(Symbol)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitWinCFIStartProc(Symbol, Loc); return false; @@ -718,8 +698,8 @@ bool COFFAsmParser::parseSEHDirectiveEndChained(StringRef, SMLoc Loc) { } bool COFFAsmParser::parseSEHDirectiveHandler(StringRef, SMLoc Loc) { - StringRef SymbolID; - if (getParser().parseIdentifier(SymbolID)) + MCSymbol *handler; + if (getParser().parseSymbol(handler)) return true; if (getLexer().isNot(AsmToken::Comma)) @@ -736,8 +716,6 @@ bool COFFAsmParser::parseSEHDirectiveHandler(StringRef, SMLoc Loc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID); - Lex(); getStreamer().emitWinEHHandler(handler, unwind, except, Loc); return false; diff --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp index 282f22fd33609..b855a765e8d26 100644 --- a/llvm/lib/MC/MCParser/COFFMasmParser.cpp +++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp @@ -444,8 +444,8 @@ bool COFFMasmParser::parseDirectiveProc(StringRef Directive, SMLoc Loc) { if (!getStreamer().getCurrentFragment()) return Error(getTok().getLoc(), "expected section directive"); - StringRef Label; - if (getParser().parseIdentifier(Label)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return Error(Loc, "expected identifier for procedure"); if (getLexer().is(AsmToken::Identifier)) { StringRef nextVal = getTok().getString(); @@ -460,11 +460,12 @@ bool COFFMasmParser::parseDirectiveProc(StringRef Directive, SMLoc Loc) { nextLoc = getTok().getLoc(); } } - MCSymbolCOFF *Sym = cast(getContext().getOrCreateSymbol(Label)); // Define symbol as simple external function - Sym->setExternal(true); - Sym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT); + auto *COFFSym = cast(Sym); + COFFSym->setExternal(true); + COFFSym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION + << COFF::SCT_COMPLEX_TYPE_SHIFT); bool Framed = false; if (getLexer().is(AsmToken::Identifier) && @@ -475,7 +476,7 @@ bool COFFMasmParser::parseDirectiveProc(StringRef Directive, SMLoc Loc) { } getStreamer().emitLabel(Sym, Loc); - CurrentProcedures.push_back(Label); + CurrentProcedures.push_back(Sym->getName()); CurrentProceduresFramed.push_back(Framed); return false; } @@ -510,8 +511,8 @@ bool COFFMasmParser::parseDirectiveAlias(StringRef Directive, SMLoc Loc) { getParser().parseAngleBracketString(ActualName)) return Error(getTok().getLoc(), "expected "); - MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); - MCSymbol *Actual = getContext().getOrCreateSymbol(ActualName); + MCSymbol *Alias = getContext().parseSymbol(AliasName); + MCSymbol *Actual = getContext().parseSymbol(ActualName); getStreamer().emitWeakReference(Alias, Actual); diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index a9095b3298f5e..fceb718d091c9 100644 --- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -501,13 +501,10 @@ bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section, /// parseDirectiveAltEntry /// ::= .alt_entry identifier bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Look up symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (Sym->isDefined()) return TokError(".alt_entry must preceed symbol definition"); @@ -521,13 +518,10 @@ bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { /// parseDirectiveDesc /// ::= .desc identifier , expression bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in '.desc' directive"); Lex(); @@ -560,18 +554,17 @@ bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { return Error(Loc, "indirect symbol not in a symbol pointer or stub " "section"); - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in .indirect_symbol directive"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - // Assembler local symbols don't make any sense here. Complain loudly. if (Sym->isTemporary()) return TokError("non-local symbol required in directive"); if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol)) - return TokError("unable to emit indirect symbol attribute for: " + Name); + return TokError("unable to emit indirect symbol attribute for: " + + Sym->getName()); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.indirect_symbol' directive"); @@ -633,13 +626,10 @@ bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { /// parseDirectiveLsym /// ::= .lsym identifier , expression bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in '.lsym' directive"); Lex(); @@ -826,13 +816,10 @@ bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { /// ::= .tbss identifier, size, align bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) { SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); @@ -911,13 +898,10 @@ bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) { Lex(); SMLoc IDLoc = getLexer().getLoc(); - StringRef IDStr; - if (getParser().parseIdentifier(IDStr)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - // handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr); - if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index ec8b40261a6ca..b04ec64517721 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -164,7 +164,7 @@ bool ELFAsmParser::parseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { continue; } - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + MCSymbol *Sym = getContext().parseSymbol(Name); getStreamer().emitSymbolAttribute(Sym, Attr); @@ -197,10 +197,9 @@ bool ELFAsmParser::parseSectionSwitch(StringRef Section, unsigned Type, } bool ELFAsmParser::parseDirectiveSize(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier"); - MCSymbolELF *Sym = cast(getContext().getOrCreateSymbol(Name)); if (getLexer().isNot(AsmToken::Comma)) return TokError("expected comma"); @@ -711,13 +710,10 @@ static MCSymbolAttr MCAttrForString(StringRef Type) { /// ::= .type identifier , %attribute /// ::= .type identifier , "attribute" bool ELFAsmParser::parseDirectiveType(StringRef, SMLoc) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - bool AllowAt = getLexer().getAllowAtInIdentifier(); if (!AllowAt && !getContext().getAsmInfo()->getCommentString().starts_with("@")) @@ -789,8 +785,9 @@ bool ELFAsmParser::parseDirectiveIdent(StringRef, SMLoc) { /// parseDirectiveSymver /// ::= .symver foo, bar2@zed bool ELFAsmParser::parseDirectiveSymver(StringRef, SMLoc) { - StringRef OriginalName, Name, Action; - if (getParser().parseIdentifier(OriginalName)) + MCSymbol *OriginalSym; + StringRef Name, Action; + if (getParser().parseSymbol(OriginalSym)) return TokError("expected identifier"); if (getLexer().isNot(AsmToken::Comma)) @@ -818,8 +815,7 @@ bool ELFAsmParser::parseDirectiveSymver(StringRef, SMLoc) { } (void)parseOptionalToken(AsmToken::EndOfStatement); - getStreamer().emitELFSymverDirective( - getContext().getOrCreateSymbol(OriginalName), Name, KeepOriginalSym); + getStreamer().emitELFSymverDirective(OriginalSym, Name, KeepOriginalSym); return false; } @@ -852,8 +848,8 @@ bool ELFAsmParser::parseDirectiveVersion(StringRef, SMLoc) { bool ELFAsmParser::parseDirectiveWeakref(StringRef, SMLoc) { // FIXME: Share code with the other alias building directives. - StringRef AliasName; - if (getParser().parseIdentifier(AliasName)) + MCSymbol *Alias; + if (getParser().parseSymbol(Alias)) return TokError("expected identifier"); if (getLexer().isNot(AsmToken::Comma)) @@ -861,14 +857,10 @@ bool ELFAsmParser::parseDirectiveWeakref(StringRef, SMLoc) { Lex(); - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier"); - MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - getStreamer().emitWeakReference(Alias, Sym); return false; } diff --git a/llvm/lib/MC/MCParser/MCAsmParser.cpp b/llvm/lib/MC/MCParser/MCAsmParser.cpp index 68b9cab2492f5..c1b7e57184de1 100644 --- a/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -163,6 +163,15 @@ bool MCAsmParser::parseGNUAttribute(SMLoc L, int64_t &Tag, return true; } +bool MCAsmParser::parseSymbol(MCSymbol *&Res) { + StringRef Name; + if (parseIdentifier(Name)) + return true; + + Res = getContext().parseSymbol(Name); + return false; +} + void MCParsedAsmOperand::dump() const { // Cannot completely remove virtual function even in release mode. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp index 7fa05088c9725..299d4b46a8a84 100644 --- a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp +++ b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp @@ -50,8 +50,8 @@ bool MCAsmParserExtension::parseDirectiveCGProfile(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - MCSymbol *FromSym = getContext().getOrCreateSymbol(From); - MCSymbol *ToSym = getContext().getOrCreateSymbol(To); + MCSymbol *FromSym = getContext().parseSymbol(From); + MCSymbol *ToSym = getContext().parseSymbol(To); getStreamer().emitCGProfileEntry( MCSymbolRefExpr::create(FromSym, getContext(), FromLoc), diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp index f4684e64e8628..3730c63b04233 100644 --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -1480,7 +1480,7 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, auto VarIt = Variables.find(SymbolName.lower()); if (VarIt != Variables.end()) SymbolName = VarIt->second.Name; - Sym = getContext().getOrCreateSymbol(SymbolName); + Sym = getContext().parseSymbol(SymbolName); } // If this is an absolute variable reference, substitute it now to preserve @@ -1965,7 +1965,7 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info, if (IDVal == "@@") { Sym = Ctx.createDirectionalLocalSymbol(0); } else { - Sym = getContext().getOrCreateSymbol(IDVal); + Sym = getContext().parseSymbol(IDVal); } // End of Labels should be treated as end of line for lexing @@ -3009,8 +3009,7 @@ bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name, return false; } - MCSymbol *Sym = getContext().getOrCreateSymbol(Var.Name); - + auto *Sym = getContext().parseSymbol(Var.Name); const MCConstantExpr *PrevValue = Sym->isVariable() ? dyn_cast_or_null(Sym->getVariableValue()) @@ -3318,7 +3317,7 @@ bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size, StringRef Name, SMLoc NameLoc) { if (StructInProgress.empty()) { // Initialize named data value. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + MCSymbol *Sym = getContext().parseSymbol(Name); getStreamer().emitLabel(Sym); unsigned Count; if (emitIntegralValues(Size, &Count)) @@ -3509,7 +3508,7 @@ bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName, SMLoc NameLoc) { if (StructInProgress.empty()) { // Initialize named data value. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + MCSymbol *Sym = getContext().parseSymbol(Name); getStreamer().emitLabel(Sym); unsigned Count; if (emitRealValues(Semantics, &Count)) @@ -4003,7 +4002,7 @@ bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure, SMLoc DirLoc, StringRef Name) { if (StructInProgress.empty()) { // Initialize named data value. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + MCSymbol *Sym = getContext().parseSymbol(Name); getStreamer().emitLabel(Sym); unsigned Count; if (emitStructValues(Structure, &Count)) @@ -4504,9 +4503,9 @@ bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { bool MasmParser::parseDirectiveExtern() { // .extern is the default - but we still need to take any provided type info. auto parseOp = [&]() -> bool { - StringRef Name; + MCSymbol *Sym; SMLoc NameLoc = getTok().getLoc(); - if (parseIdentifier(Name)) + if (parseSymbol(Sym)) return Error(NameLoc, "expected name"); if (parseToken(AsmToken::Colon)) return true; @@ -4519,10 +4518,9 @@ bool MasmParser::parseDirectiveExtern() { AsmTypeInfo Type; if (lookUpType(TypeName, Type)) return Error(TypeLoc, "unrecognized type"); - KnownType[Name.lower()] = Type; + KnownType[Sym->getName().lower()] = Type; } - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); Sym->setExternal(true); getStreamer().emitSymbolAttribute(Sym, MCSA_Extern); @@ -4538,11 +4536,10 @@ bool MasmParser::parseDirectiveExtern() { /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { auto parseOp = [&]() -> bool { - StringRef Name; SMLoc Loc = getTok().getLoc(); - if (parseIdentifier(Name)) + MCSymbol *Sym; + if (parseSymbol(Sym)) return Error(Loc, "expected identifier"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); // Assembler local symbols don't make any sense here. Complain loudly. if (Sym->isTemporary()) @@ -4565,13 +4562,10 @@ bool MasmParser::parseDirectiveComm(bool IsLocal) { return true; SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (parseIdentifier(Name)) + MCSymbol *Sym; + if (parseSymbol(Sym)) return TokError("expected identifier in directive"); - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) return TokError("unexpected token in directive"); Lex(); diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp index 1f824b80bcd4b..61534c6436ac6 100644 --- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp +++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp @@ -213,10 +213,9 @@ class WasmAsmParser : public MCAsmParserExtension { // TODO: This function is almost the same as ELFAsmParser::ParseDirectiveSize // so maybe could be shared somehow. bool parseDirectiveSize(StringRef, SMLoc Loc) { - StringRef Name; - if (Parser->parseIdentifier(Name)) + MCSymbol *Sym; + if (Parser->parseSymbol(Sym)) return TokError("expected identifier in directive"); - auto Sym = getContext().getOrCreateSymbol(Name); if (expect(AsmToken::Comma, ",")) return true; const MCExpr *Expr; @@ -241,9 +240,8 @@ class WasmAsmParser : public MCAsmParserExtension { if (!Lexer->is(AsmToken::Identifier)) return error("Expected label after .type directive, got: ", Lexer->getTok()); - auto WasmSym = cast( - getStreamer().getContext().getOrCreateSymbol( - Lexer->getTok().getString())); + auto *WasmSym = cast( + getStreamer().getContext().parseSymbol(Lexer->getTok().getString())); Lex(); if (!(isNext(AsmToken::Comma) && isNext(AsmToken::At) && Lexer->is(AsmToken::Identifier))) @@ -294,10 +292,9 @@ class WasmAsmParser : public MCAsmParserExtension { assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); if (getLexer().isNot(AsmToken::EndOfStatement)) { while (true) { - StringRef Name; - if (getParser().parseIdentifier(Name)) + MCSymbol *Sym; + if (getParser().parseSymbol(Sym)) return TokError("expected identifier in directive"); - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); getStreamer().emitSymbolAttribute(Sym, Attr); if (getLexer().is(AsmToken::EndOfStatement)) break; diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index beb472b7c7deb..97f591fbf0e28 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -63,6 +63,8 @@ LLVM_DUMP_METHOD void MCSection::dump( raw_ostream &OS = errs(); OS << "MCSection Name:" << getName(); + if (isLinkerRelaxable()) + OS << " LinkerRelaxable"; for (auto &F : *this) { OS << '\n'; F.dump(); @@ -82,11 +84,11 @@ LLVM_DUMP_METHOD void MCSection::dump( void MCEncodedFragment::setContents(ArrayRef Contents) { auto &S = getParent()->ContentStorage; - if (ContentStart + Contents.size() > ContentEnd) { + if (Contents.size() > ContentSize) { ContentStart = S.size(); S.resize_for_overwrite(S.size() + Contents.size()); } - ContentEnd = ContentStart + Contents.size(); + ContentSize = Contents.size(); llvm::copy(Contents, S.begin() + ContentStart); } diff --git a/llvm/lib/ObjCopy/COFF/COFFObject.cpp b/llvm/lib/ObjCopy/COFF/COFFObject.cpp index 5fa13391c908f..91cf7e32a7396 100644 --- a/llvm/lib/ObjCopy/COFF/COFFObject.cpp +++ b/llvm/lib/ObjCopy/COFF/COFFObject.cpp @@ -18,6 +18,8 @@ using namespace object; void Object::addSymbols(ArrayRef NewSymbols) { for (Symbol S : NewSymbols) { S.UniqueId = NextSymbolUniqueId++; + S.OriginalRawIndex = NextSymbolOriginalIndex; + NextSymbolOriginalIndex += 1 + S.Sym.NumberOfAuxSymbols; Symbols.emplace_back(S); } updateSymbols(); diff --git a/llvm/lib/ObjCopy/COFF/COFFObject.h b/llvm/lib/ObjCopy/COFF/COFFObject.h index cdd1f17fc6055..6b70add1bb1b7 100644 --- a/llvm/lib/ObjCopy/COFF/COFFObject.h +++ b/llvm/lib/ObjCopy/COFF/COFFObject.h @@ -89,6 +89,7 @@ struct Symbol { std::optional WeakTargetSymbolId; size_t UniqueId; size_t RawIndex; + size_t OriginalRawIndex; bool Referenced; }; @@ -140,6 +141,7 @@ struct Object { DenseMap SymbolMap; size_t NextSymbolUniqueId = 0; + size_t NextSymbolOriginalIndex = 0; std::vector
Sections; DenseMap SectionMap; diff --git a/llvm/lib/ObjCopy/COFF/COFFReader.cpp b/llvm/lib/ObjCopy/COFF/COFFReader.cpp index 62a71d41ded5f..9b55f76e58404 100644 --- a/llvm/lib/ObjCopy/COFF/COFFReader.cpp +++ b/llvm/lib/ObjCopy/COFF/COFFReader.cpp @@ -135,7 +135,7 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const { // it is, find the target section unique id. const coff_aux_section_definition *SD = SymRef.getSectionDefinition(); const coff_aux_weak_external *WE = SymRef.getWeakExternal(); - if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE && !Obj.IsPE) { int32_t Index = SD->getNumber(IsBigObj); if (Index <= 0 || static_cast(Index - 1) >= Sections.size()) return createStringError(object_error::parse_failed, diff --git a/llvm/lib/ObjCopy/COFF/COFFWriter.cpp b/llvm/lib/ObjCopy/COFF/COFFWriter.cpp index 350c4aec572c9..fed67d67f13a7 100644 --- a/llvm/lib/ObjCopy/COFF/COFFWriter.cpp +++ b/llvm/lib/ObjCopy/COFF/COFFWriter.cpp @@ -12,6 +12,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/CRC.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include @@ -92,6 +94,77 @@ Error COFFWriter::finalizeSymbolContents() { return Error::success(); } +Error COFFWriter::finalizeSymIdxContents() { + // CFGuards shouldn't be present in PE. + if (Obj.IsPE) + return Error::success(); + + // Currently handle only sections consisting only of .symidx. + // TODO: other sections such as .impcall and .hybmp$x require more complex + // handling as they have more complex layout. + auto IsSymIdxSection = [](StringRef Name) { + return Name == ".gljmp$y" || Name == ".giats$y" || Name == ".gfids$y" || + Name == ".gehcont$y"; + }; + + DenseMap SymIdMap; + SmallDenseMap SecIdMap; + for (Symbol &Sym : Obj.getMutableSymbols()) { + SymIdMap[Sym.OriginalRawIndex] = Sym.RawIndex; + + // We collect only definition symbols of the sections to update the + // checksums. + if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC && + Sym.Sym.NumberOfAuxSymbols == 1 && Sym.Sym.Value == 0 && + IsSymIdxSection(Sym.Name)) + SecIdMap[Sym.TargetSectionId] = + reinterpret_cast( + Sym.AuxData[0].Opaque); + } + + for (Section &Sec : Obj.getMutableSections()) { + if (!IsSymIdxSection(Sec.Name)) + continue; + + ArrayRef RawIds = Sec.getContents(); + // Nothing to do and also the checksum will be -1 instead of 0 if we + // recalculate it on empty input. + if (RawIds.size() == 0) + continue; + + auto SecDefIt = SecIdMap.find(Sec.UniqueId); + if (SecDefIt == SecIdMap.end()) + return createStringError(object_error::invalid_symbol_index, + "section '%s' does not have the corresponding " + "symbol or the symbol has unexpected format", + Sec.Name.str().c_str()); + + // Create updated content. + ArrayRef Ids( + reinterpret_cast(RawIds.data()), + RawIds.size() / 4); + std::vector NewIds; + for (support::ulittle32_t Id : Ids) { + auto SymIdIt = SymIdMap.find(Id); + if (SymIdIt == SymIdMap.end()) + return createStringError(object_error::invalid_symbol_index, + "section '%s' contains a .symidx (%d) that is " + "incorrect or was stripped", + Sec.Name.str().c_str(), Id.value()); + NewIds.push_back(support::ulittle32_t(SymIdIt->getSecond())); + } + ArrayRef NewRawIds(reinterpret_cast(NewIds.data()), + RawIds.size()); + // Update the checksum. + JamCRC JC(/*Init=*/0); + JC.update(NewRawIds); + SecDefIt->getSecond()->CheckSum = JC.getCRC(); + // Set new content. + Sec.setOwnedContents(NewRawIds.vec()); + } + return Error::success(); +} + void COFFWriter::layoutSections() { for (auto &S : Obj.getMutableSections()) { if (S.Header.SizeOfRawData > 0) @@ -183,6 +256,8 @@ Error COFFWriter::finalize(bool IsBigObj) { return E; if (Error E = finalizeSymbolContents()) return E; + if (Error E = finalizeSymIdxContents()) + return E; size_t SizeOfHeaders = 0; FileAlignment = 1; diff --git a/llvm/lib/ObjCopy/COFF/COFFWriter.h b/llvm/lib/ObjCopy/COFF/COFFWriter.h index b7dca69e9a81a..66d7f01c87f18 100644 --- a/llvm/lib/ObjCopy/COFF/COFFWriter.h +++ b/llvm/lib/ObjCopy/COFF/COFFWriter.h @@ -34,6 +34,7 @@ class COFFWriter { template std::pair finalizeSymbolTable(); Error finalizeRelocTargets(); Error finalizeSymbolContents(); + Error finalizeSymIdxContents(); void layoutSections(); Expected finalizeStringTable(); diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 0e13d32bbe522..a6b56ae77cf21 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -620,7 +620,10 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { StringRef ELFObjectFileBase::getNVPTXCPUName() const { assert(getEMachine() == ELF::EM_CUDA); - unsigned SM = getPlatformFlags() & ELF::EF_CUDA_SM; + unsigned SM = getEIdentABIVersion() == ELF::ELFABIVERSION_CUDA_V1 + ? getPlatformFlags() & ELF::EF_CUDA_SM + : (getPlatformFlags() & ELF::EF_CUDA_SM_MASK) >> + ELF::EF_CUDA_SM_OFFSET; switch (SM) { // Fermi architecture. @@ -672,6 +675,8 @@ StringRef ELFObjectFileBase::getNVPTXCPUName() const { return "sm_86"; case ELF::EF_CUDA_SM87: return "sm_87"; + case ELF::EF_CUDA_SM88: + return "sm_88"; // Ada architecture. case ELF::EF_CUDA_SM89: @@ -679,7 +684,30 @@ StringRef ELFObjectFileBase::getNVPTXCPUName() const { // Hopper architecture. case ELF::EF_CUDA_SM90: - return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_90a" : "sm_90"; + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS_V1 ? "sm_90a" + : "sm_90"; + + // Blackwell architecture. + case ELF::EF_CUDA_SM100: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_100a" + : "sm_100"; + case ELF::EF_CUDA_SM101: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_101a" + : "sm_101"; + case ELF::EF_CUDA_SM103: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_103a" + : "sm_103"; + case ELF::EF_CUDA_SM110: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_110a" + : "sm_110"; + + // Blackwell architecture. + case ELF::EF_CUDA_SM120: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_120a" + : "sm_120"; + case ELF::EF_CUDA_SM121: + return getPlatformFlags() & ELF::EF_CUDA_ACCELERATORS ? "sm_121a" + : "sm_121"; default: llvm_unreachable("Unknown EF_CUDA_SM value"); } diff --git a/llvm/lib/Support/BLAKE3/blake3_dispatch.c b/llvm/lib/Support/BLAKE3/blake3_dispatch.c index d00580fe35195..19918aa708b2f 100644 --- a/llvm/lib/Support/BLAKE3/blake3_dispatch.c +++ b/llvm/lib/Support/BLAKE3/blake3_dispatch.c @@ -236,7 +236,7 @@ void blake3_xof_many(const uint32_t cv[8], #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); -#if !defined(_WIN32) && !defined(BLAKE3_NO_AVX512) +#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_xof_many_avx512(cv, block, block_len, counter, flags, out, outblocks); return; diff --git a/llvm/lib/Support/BLAKE3/blake3_impl.h b/llvm/lib/Support/BLAKE3/blake3_impl.h index deed079e468a5..dd71e729f208f 100644 --- a/llvm/lib/Support/BLAKE3/blake3_impl.h +++ b/llvm/lib/Support/BLAKE3/blake3_impl.h @@ -324,7 +324,7 @@ void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__CYGWIN__) LLVM_LIBRARY_VISIBILITY void blake3_xof_many_avx512(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], diff --git a/llvm/lib/Support/BLAKE3/blake3_neon.c b/llvm/lib/Support/BLAKE3/blake3_neon.c index 9629e10836864..ee36721f87573 100644 --- a/llvm/lib/Support/BLAKE3/blake3_neon.c +++ b/llvm/lib/Support/BLAKE3/blake3_neon.c @@ -245,10 +245,11 @@ INLINE void load_counters4(uint64_t counter, bool increment_counter, counter_high(counter + (mask & 2)), counter_high(counter + (mask & 3))); } -void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks, - const uint32_t key[8], uint64_t counter, - bool increment_counter, uint8_t flags, - uint8_t flags_start, uint8_t flags_end, uint8_t *out) { +static void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks, + const uint32_t key[8], uint64_t counter, + bool increment_counter, uint8_t flags, + uint8_t flags_start, uint8_t flags_end, + uint8_t *out) { uint32x4_t h_vecs[8] = { set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]), set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]), diff --git a/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h b/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h index d5be360815add..d24657465dd8f 100644 --- a/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h +++ b/llvm/lib/Support/BLAKE3/llvm_blake3_prefix.h @@ -10,7 +10,9 @@ #define blake3_hasher llvm_blake3_hasher #define blake3_chunk_state llvm_blake3_chunk_state #define blake3_compress_in_place llvm_blake3_compress_in_place +#define blake3_compress_subtree_wide llvm_blake3_compress_subtree_wide #define blake3_compress_xof llvm_blake3_compress_xof +#define blake3_xof_many llvm_blake3_xof_many #define blake3_hash_many llvm_blake3_hash_many #define blake3_simd_degree llvm_blake3_simd_degree #define blake3_compress_in_place_portable llvm_blake3_compress_in_place_portable diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index 601f11f6d23c8..1c4645ad83641 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -501,8 +501,14 @@ getOpenFileImpl(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, std::unique_ptr Result( new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile( RequiresNullTerminator, FD, MapSize, Offset, EC)); - if (!EC) - return std::move(Result); + if (!EC) { + // On at least Linux, and possibly on other systems, mmap may return pages + // from the page cache that are not properly filled with trailing zeroes, + // if some prior user of the page wrote non-zero bytes. Detect this and + // don't use mmap in that case. + if (!RequiresNullTerminator || *Result->getBufferEnd() == '\0') + return std::move(Result); + } } #ifdef __MVS__ diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc index d862dbd7f71c9..9c584415e0cbe 100644 --- a/llvm/lib/Support/Windows/Threading.inc +++ b/llvm/lib/Support/Windows/Threading.inc @@ -42,6 +42,9 @@ void llvm_thread_join_impl(HANDLE hThread) { if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) { ReportLastErrorFatal("WaitForSingleObject failed"); } + if (::CloseHandle(hThread) == FALSE) { + ReportLastErrorFatal("CloseHandle failed"); + } } void llvm_thread_detach_impl(HANDLE hThread) { diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index c4b43e1b51265..4bd650b37792e 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -2195,13 +2195,24 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) { if (BrTarget == AddrDisc) report_fatal_error("Branch target is signed with its own value"); - // If we are printing BLRA pseudo instruction, then x16 and x17 are - // implicit-def'ed by the MI and AddrDisc is not used as any other input, so - // try to save one MOV by setting MayUseAddrAsScratch. + // If we are printing BLRA pseudo, try to save one MOV by making use of the + // fact that x16 and x17 are described as clobbered by the MI instruction and + // AddrDisc is not used as any other input. + // + // Back in the day, emitPtrauthDiscriminator was restricted to only returning + // either x16 or x17, meaning the returned register is always among the + // implicit-def'ed registers of BLRA pseudo. Now this property can be violated + // if isX16X17Safer predicate is false, thus manually check if AddrDisc is + // among x16 and x17 to prevent clobbering unexpected registers. + // // Unlike BLRA, BRA pseudo is used to perform computed goto, and thus not // declared as clobbering x16/x17. + // + // FIXME: Make use of `killed` flags and register masks instead. + bool AddrDiscIsImplicitDef = + IsCall && (AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17); Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17, - /*MayUseAddrAsScratch=*/IsCall); + AddrDiscIsImplicitDef); bool IsZeroDisc = DiscReg == AArch64::XZR; unsigned Opc; @@ -2930,8 +2941,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { // See the comments in emitPtrauthBranch. if (Callee == AddrDisc) report_fatal_error("Call target is signed with its own value"); + + // After isX16X17Safer predicate was introduced, emitPtrauthDiscriminator is + // no longer restricted to only reusing AddrDisc when it is X16 or X17 + // (which are implicit-def'ed by AUTH_TCRETURN pseudos), thus impose this + // restriction manually not to clobber an unexpected register. + bool AddrDiscIsImplicitDef = + AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17; Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg, - /*MayUseAddrAsScratch=*/true); + AddrDiscIsImplicitDef); const bool IsZero = DiscReg == AArch64::XZR; const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ}, diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp index 3436dc9ef4521..137ff898e86a3 100644 --- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp +++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp @@ -30,6 +30,14 @@ using namespace llvm; #define AARCH64_BRANCH_TARGETS_NAME "AArch64 Branch Targets" namespace { +// BTI HINT encoding: base (32) plus 'c' (2) and/or 'j' (4). +enum : unsigned { + BTIBase = 32, // Base immediate for BTI HINT + BTIC = 1u << 1, // 2 + BTIJ = 1u << 2, // 4 + BTIMask = BTIC | BTIJ, +}; + class AArch64BranchTargets : public MachineFunctionPass { public: static char ID; @@ -42,6 +50,7 @@ class AArch64BranchTargets : public MachineFunctionPass { void addBTI(MachineBasicBlock &MBB, bool CouldCall, bool CouldJump, bool NeedsWinCFI); }; + } // end anonymous namespace char AArch64BranchTargets::ID = 0; @@ -62,9 +71,8 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) { if (!MF.getInfo()->branchTargetEnforcement()) return false; - LLVM_DEBUG( - dbgs() << "********** AArch64 Branch Targets **********\n" - << "********** Function: " << MF.getName() << '\n'); + LLVM_DEBUG(dbgs() << "********** AArch64 Branch Targets **********\n" + << "********** Function: " << MF.getName() << '\n'); const Function &F = MF.getFunction(); // LLVM does not consider basic blocks which are the targets of jump tables @@ -103,6 +111,12 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) { JumpTableTargets.count(&MBB)) CouldJump = true; + if (MBB.isEHPad()) { + if (HasWinCFI && (MBB.isEHFuncletEntry() || MBB.isCleanupFuncletEntry())) + CouldCall = true; + else + CouldJump = true; + } if (CouldCall || CouldJump) { addBTI(MBB, CouldCall, CouldJump, HasWinCFI); MadeChange = true; @@ -130,7 +144,12 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall, auto MBBI = MBB.begin(); - // Skip the meta instructions, those will be removed anyway. + // If the block starts with EH_LABEL(s), skip them first. + while (MBBI != MBB.end() && MBBI->isEHLabel()) { + ++MBBI; + } + + // Skip meta/CFI/etc. (and EMITBKEY) to reach the first executable insn. for (; MBBI != MBB.end() && (MBBI->isMetaInstruction() || MBBI->getOpcode() == AArch64::EMITBKEY); ++MBBI) @@ -138,16 +157,21 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall, // SCTLR_EL1.BT[01] is set to 0 by default which means // PACI[AB]SP are implicitly BTI C so no BTI C instruction is needed there. - if (MBBI != MBB.end() && HintNum == 34 && + if (MBBI != MBB.end() && ((HintNum & BTIMask) == BTIC) && (MBBI->getOpcode() == AArch64::PACIASP || MBBI->getOpcode() == AArch64::PACIBSP)) return; - if (HasWinCFI && MBBI->getFlag(MachineInstr::FrameSetup)) { - BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()), - TII->get(AArch64::SEH_Nop)); + // Insert BTI exactly at the first executable instruction. + const DebugLoc DL = MBB.findDebugLoc(MBBI); + MachineInstr *BTI = BuildMI(MBB, MBBI, DL, TII->get(AArch64::HINT)) + .addImm(HintNum) + .getInstr(); + + // WinEH: put .seh_nop after BTI when the first real insn is FrameSetup. + if (HasWinCFI && MBBI != MBB.end() && + MBBI->getFlag(MachineInstr::FrameSetup)) { + auto AfterBTI = std::next(MachineBasicBlock::iterator(BTI)); + BuildMI(MBB, AfterBTI, DL, TII->get(AArch64::SEH_Nop)); } - BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()), - TII->get(AArch64::HINT)) - .addImm(HintNum); } diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 36f3a670808d4..7de66ccbf6f29 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -671,8 +671,8 @@ bool AArch64ExpandPseudo::expand_DestructiveOp( } if (PRFX) { - finalizeBundle(MBB, PRFX->getIterator(), MBBI->getIterator()); transferImpOps(MI, PRFX, DOP); + finalizeBundle(MBB, PRFX->getIterator(), MBBI->getIterator()); } else transferImpOps(MI, DOP, DOP); @@ -1591,18 +1591,22 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, "Non-writeback variants of STGloop / STZGloop should not " "survive past PrologEpilogInserter."); case AArch64::STR_ZZZZXI: + case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS: return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 4); case AArch64::STR_ZZZXI: return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 3); case AArch64::STR_ZZXI: + case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS: return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 2); case AArch64::STR_PPXI: return expandSVESpillFill(MBB, MBBI, AArch64::STR_PXI, 2); case AArch64::LDR_ZZZZXI: + case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS: return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 4); case AArch64::LDR_ZZZXI: return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 3); case AArch64::LDR_ZZXI: + case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS: return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 2); case AArch64::LDR_PPXI: return expandSVESpillFill(MBB, MBBI, AArch64::LDR_PXI, 2); diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index 9973df865ea17..12159a9519737 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -923,8 +923,8 @@ def HasV9_5aOps : Architecture64<9, 5, "a", "v9.5a", [HasV9_4aOps, FeatureCPA], !listconcat(HasV9_4aOps.DefaultExts, [FeatureCPA, FeatureLUT, FeatureFAMINMAX])>; def HasV9_6aOps : Architecture64<9, 6, "a", "v9.6a", - [HasV9_5aOps, FeatureCMPBR, FeatureFPRCVT, FeatureSVE2p2, FeatureLSUI, FeatureOCCMO], - !listconcat(HasV9_5aOps.DefaultExts, [FeatureCMPBR, FeatureFPRCVT, FeatureSVE2p2, + [HasV9_5aOps, FeatureCMPBR, FeatureLSUI, FeatureOCCMO], + !listconcat(HasV9_5aOps.DefaultExts, [FeatureCMPBR, FeatureLSUI, FeatureOCCMO])>; def HasV8_0rOps : Architecture64<8, 0, "r", "v8r", [ //v8.1 diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index c1474773faa76..5420545cc3cec 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2482,8 +2482,10 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned Opc) { case AArch64::LDR_PXI: case AArch64::LDR_ZXI: case AArch64::LDR_ZZXI: + case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS: case AArch64::LDR_ZZZXI: case AArch64::LDR_ZZZZXI: + case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS: case AArch64::LDRBBui: case AArch64::LDRBui: case AArch64::LDRDui: @@ -2525,8 +2527,10 @@ unsigned AArch64InstrInfo::getLoadStoreImmIdx(unsigned Opc) { case AArch64::STR_PXI: case AArch64::STR_ZXI: case AArch64::STR_ZZXI: + case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS: case AArch64::STR_ZZZXI: case AArch64::STR_ZZZZXI: + case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS: case AArch64::STRBBui: case AArch64::STRBui: case AArch64::STRDui: @@ -4318,7 +4322,9 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale, break; // SVE case AArch64::STR_ZZZZXI: + case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS: case AArch64::LDR_ZZZZXI: + case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS: Scale = TypeSize::getScalable(16); Width = TypeSize::getScalable(16 * 4); MinOffset = -256; @@ -4332,7 +4338,9 @@ bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale, MaxOffset = 253; break; case AArch64::STR_ZZXI: + case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS: case AArch64::LDR_ZZXI: + case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS: Scale = TypeSize::getScalable(16); Width = TypeSize::getScalable(16 * 2); MinOffset = -256; @@ -5559,8 +5567,12 @@ void AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, assert(Subtarget.hasNEON() && "Unexpected register store without NEON"); Opc = AArch64::ST1Twov2d; Offset = false; - } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC) || - AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) { + } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) { + assert(Subtarget.isSVEorStreamingSVEAvailable() && + "Unexpected register store without SVE store instructions"); + Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS; + StackID = TargetStackID::ScalableVector; + } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) { assert(Subtarget.isSVEorStreamingSVEAvailable() && "Unexpected register store without SVE store instructions"); Opc = AArch64::STR_ZZXI; @@ -5584,8 +5596,12 @@ void AArch64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, assert(Subtarget.hasNEON() && "Unexpected register store without NEON"); Opc = AArch64::ST1Fourv2d; Offset = false; - } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC) || - AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) { + } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) { + assert(Subtarget.isSVEorStreamingSVEAvailable() && + "Unexpected register store without SVE store instructions"); + Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS; + StackID = TargetStackID::ScalableVector; + } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) { assert(Subtarget.isSVEorStreamingSVEAvailable() && "Unexpected register store without SVE store instructions"); Opc = AArch64::STR_ZZZZXI; @@ -5736,8 +5752,12 @@ void AArch64InstrInfo::loadRegFromStackSlot( assert(Subtarget.hasNEON() && "Unexpected register load without NEON"); Opc = AArch64::LD1Twov2d; Offset = false; - } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC) || - AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) { + } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) { + assert(Subtarget.isSVEorStreamingSVEAvailable() && + "Unexpected register load without SVE load instructions"); + Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS; + StackID = TargetStackID::ScalableVector; + } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) { assert(Subtarget.isSVEorStreamingSVEAvailable() && "Unexpected register load without SVE load instructions"); Opc = AArch64::LDR_ZZXI; @@ -5761,8 +5781,12 @@ void AArch64InstrInfo::loadRegFromStackSlot( assert(Subtarget.hasNEON() && "Unexpected register load without NEON"); Opc = AArch64::LD1Fourv2d; Offset = false; - } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC) || - AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) { + } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) { + assert(Subtarget.isSVEorStreamingSVEAvailable() && + "Unexpected register load without SVE load instructions"); + Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS; + StackID = TargetStackID::ScalableVector; + } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) { assert(Subtarget.isSVEorStreamingSVEAvailable() && "Unexpected register load without SVE load instructions"); Opc = AArch64::LDR_ZZZZXI; diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index ddc685fae5e9a..bbcd6824473cf 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -2148,7 +2148,7 @@ let Predicates = [HasPAuth] in { i64imm:$Disc, GPR64:$AddrDisc), [], "$AuthVal = $Val">, Sched<[WriteI, ReadI]> { let isCodeGenOnly = 1; - let hasSideEffects = 0; + let hasSideEffects = 1; let mayStore = 0; let mayLoad = 0; let Size = 32; diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index eddb96979f7b8..0c4b4f4c3ed88 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -2625,16 +2625,22 @@ let Predicates = [HasSVE_or_SME] in { // These get expanded to individual LDR_ZXI/STR_ZXI instructions in // AArch64ExpandPseudoInsts. let mayLoad = 1, hasSideEffects = 0 in { - def LDR_ZZXI : Pseudo<(outs ZZ_b_strided_and_contiguous:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def LDR_ZZXI_STRIDED_CONTIGUOUS : Pseudo<(outs ZZ_b_strided_and_contiguous:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def LDR_ZZZZXI_STRIDED_CONTIGUOUS : Pseudo<(outs ZZZZ_b_strided_and_contiguous:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + + def LDR_ZZXI : Pseudo<(outs ZZ_b:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; def LDR_ZZZXI : Pseudo<(outs ZZZ_b:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; - def LDR_ZZZZXI : Pseudo<(outs ZZZZ_b_strided_and_contiguous:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; - def LDR_PPXI : Pseudo<(outs PPR2:$pp), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def LDR_ZZZZXI : Pseudo<(outs ZZZZ_b:$Zd), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def LDR_PPXI : Pseudo<(outs PPR2:$pp), (ins GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; } let mayStore = 1, hasSideEffects = 0 in { - def STR_ZZXI : Pseudo<(outs), (ins ZZ_b_strided_and_contiguous:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def STR_ZZXI_STRIDED_CONTIGUOUS : Pseudo<(outs), (ins ZZ_b_strided_and_contiguous:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def STR_ZZZZXI_STRIDED_CONTIGUOUS : Pseudo<(outs), (ins ZZZZ_b_strided_and_contiguous:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + + def STR_ZZXI : Pseudo<(outs), (ins ZZ_b:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; def STR_ZZZXI : Pseudo<(outs), (ins ZZZ_b:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; - def STR_ZZZZXI : Pseudo<(outs), (ins ZZZZ_b_strided_and_contiguous:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; - def STR_PPXI : Pseudo<(outs), (ins PPR2:$pp, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def STR_ZZZZXI : Pseudo<(outs), (ins ZZZZ_b:$Zs, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; + def STR_PPXI : Pseudo<(outs), (ins PPR2:$pp, GPR64sp:$sp, simm4s1:$offset),[]>, Sched<[]>; } let AddedComplexity = 1 in { diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 0956823346795..2409cc862f21c 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -270,6 +270,7 @@ void AArch64Subtarget::initializeProperties(bool HasMinSize) { break; case NeoverseV2: case NeoverseV3: + CacheLineSize = 64; EpilogueVectorizationMinVF = 8; MaxInterleaveFactor = 4; ScatterOverhead = 13; diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index 07baf29ce7016..193be62b28ad6 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -3724,7 +3724,7 @@ InstructionCost AArch64TTIImpl::getCFInstrCost(unsigned Opcode, InstructionCost AArch64TTIImpl::getVectorInstrCostHelper( unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, - bool HasRealUse, const Instruction *I, Value *Scalar, + const Instruction *I, Value *Scalar, ArrayRef> ScalarUserAndIdx) const { assert(Val->isVectorTy() && "This must be a vector type"); @@ -3744,12 +3744,10 @@ InstructionCost AArch64TTIImpl::getVectorInstrCostHelper( } // The element at index zero is already inside the vector. - // - For a physical (HasRealUse==true) insert-element or extract-element + // - For a insert-element or extract-element // instruction that extracts integers, an explicit FPR -> GPR move is // needed. So it has non-zero cost. - // - For the rest of cases (virtual instruction or element type is float), - // consider the instruction free. - if (Index == 0 && (!HasRealUse || !Val->getScalarType()->isIntegerTy())) + if (Index == 0 && !Val->getScalarType()->isIntegerTy()) return 0; // This is recognising a LD1 single-element structure to one lane of one @@ -3899,25 +3897,28 @@ InstructionCost AArch64TTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index, const Value *Op0, const Value *Op1) const { - bool HasRealUse = - Opcode == Instruction::InsertElement && Op0 && !isa(Op0); - return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, HasRealUse); + // Treat insert at lane 0 into a poison vector as having zero cost. This + // ensures vector broadcasts via an insert + shuffle (and will be lowered to a + // single dup) are treated as cheap. + if (Opcode == Instruction::InsertElement && Index == 0 && Op0 && + isa(Op0)) + return 0; + return getVectorInstrCostHelper(Opcode, Val, CostKind, Index); } InstructionCost AArch64TTIImpl::getVectorInstrCost( unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar, ArrayRef> ScalarUserAndIdx) const { - return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, false, nullptr, - Scalar, ScalarUserAndIdx); + return getVectorInstrCostHelper(Opcode, Val, CostKind, Index, nullptr, Scalar, + ScalarUserAndIdx); } InstructionCost AArch64TTIImpl::getVectorInstrCost(const Instruction &I, Type *Val, TTI::TargetCostKind CostKind, unsigned Index) const { - return getVectorInstrCostHelper(I.getOpcode(), Val, CostKind, Index, - true /* HasRealUse */, &I); + return getVectorInstrCostHelper(I.getOpcode(), Val, CostKind, Index, &I); } InstructionCost AArch64TTIImpl::getScalarizationOverhead( diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h index ff0ab68a16a88..b27eb2ef7a39d 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -65,16 +65,14 @@ class AArch64TTIImpl final : public BasicTTIImplBase { // A helper function called by 'getVectorInstrCost'. // - // 'Val' and 'Index' are forwarded from 'getVectorInstrCost'; 'HasRealUse' - // indicates whether the vector instruction is available in the input IR or - // just imaginary in vectorizer passes. - /// \param ScalarUserAndIdx encodes the information about extracts from a + // 'Val' and 'Index' are forwarded from 'getVectorInstrCost'; + // \param ScalarUserAndIdx encodes the information about extracts from a /// vector with 'Scalar' being the value being extracted,'User' being the user /// of the extract(nullptr if user is not known before vectorization) and /// 'Idx' being the extract lane. InstructionCost getVectorInstrCostHelper( unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, - bool HasRealUse, const Instruction *I = nullptr, Value *Scalar = nullptr, + const Instruction *I = nullptr, Value *Scalar = nullptr, ArrayRef> ScalarUserAndIdx = {}) const; public: diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 3414fe758eff8..7b93382d1281f 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -392,8 +392,9 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, // Library functions. These default to Expand, but we have instructions // for them. setOperationAction({ISD::FCEIL, ISD::FPOW, ISD::FABS, ISD::FFLOOR, - ISD::FROUNDEVEN, ISD::FTRUNC, ISD::FMINNUM, ISD::FMAXNUM}, - MVT::f32, Legal); + ISD::FROUNDEVEN, ISD::FTRUNC}, + {MVT::f16, MVT::f32}, Legal); + setOperationAction({ISD::FMINNUM, ISD::FMAXNUM}, MVT::f32, Legal); setOperationAction(ISD::FLOG2, MVT::f32, Custom); setOperationAction(ISD::FROUND, {MVT::f32, MVT::f64}, Custom); @@ -413,9 +414,10 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FREM, {MVT::f16, MVT::f32, MVT::f64}, Custom); - if (Subtarget->has16BitInsts()) + if (Subtarget->has16BitInsts()) { setOperationAction(ISD::IS_FPCLASS, {MVT::f16, MVT::f32, MVT::f64}, Legal); - else { + setOperationAction({ISD::FLOG2, ISD::FEXP2}, MVT::f16, Legal); + } else { setOperationAction(ISD::IS_FPCLASS, {MVT::f32, MVT::f64}, Legal); setOperationAction({ISD::FLOG2, ISD::FEXP2}, MVT::f16, Custom); } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index fb72bab03e750..9593038ff2c9b 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -370,6 +370,11 @@ void ARMTargetLowering::addMVEVectorTypes(bool HasMVEFP) { setOperationAction(ISD::FMINNUM, VT, Legal); setOperationAction(ISD::FMAXNUM, VT, Legal); setOperationAction(ISD::FROUND, VT, Legal); + setOperationAction(ISD::FROUNDEVEN, VT, Legal); + setOperationAction(ISD::FRINT, VT, Legal); + setOperationAction(ISD::FTRUNC, VT, Legal); + setOperationAction(ISD::FFLOOR, VT, Legal); + setOperationAction(ISD::FCEIL, VT, Legal); setOperationAction(ISD::VECREDUCE_FADD, VT, Custom); setOperationAction(ISD::VECREDUCE_FMUL, VT, Custom); setOperationAction(ISD::VECREDUCE_FMIN, VT, Custom); @@ -1507,6 +1512,12 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_, setOperationAction(ISD::FLOG2, MVT::f16, Promote); setOperationAction(ISD::FROUND, MVT::f16, Legal); + setOperationAction(ISD::FROUNDEVEN, MVT::f16, Legal); + setOperationAction(ISD::FTRUNC, MVT::f16, Legal); + setOperationAction(ISD::FNEARBYINT, MVT::f16, Legal); + setOperationAction(ISD::FRINT, MVT::f16, Legal); + setOperationAction(ISD::FFLOOR, MVT::f16, Legal); + setOperationAction(ISD::FCEIL, MVT::f16, Legal); } if (Subtarget->hasNEON()) { diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index 3955f2a252e76..25ad9eccbce5d 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -669,7 +669,7 @@ SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, default: { // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows // us to fold the constant into the cmp instruction. - RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT); + RHS = DAG.getSignedConstant(C->getSExtValue() + 1, DL, VT); CC = ISD::SETGE; break; } @@ -713,7 +713,10 @@ SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to // fold the constant into the cmp instruction. if (const ConstantSDNode *C = dyn_cast(RHS)) { - RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT); + // Doing a "icmp ugt i16 65535, %0" comparison should have been converted + // already to something else. Assert to make sure this assumption holds. + assert((!C->isAllOnes()) && "integer overflow in comparison transform"); + RHS = DAG.getConstant(C->getZExtValue() + 1, DL, VT); CC = ISD::SETUGE; break; } diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index 1e29a0f1e85a1..9bf14ab59c7c8 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -14,6 +14,7 @@ #include "BPF.h" #include "BPFCORE.h" #include "MCTargetDesc/BPFMCTargetDesc.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -23,6 +24,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -93,7 +95,24 @@ void BTFTypeDerived::completeType(BTFDebug &BDebug) { return; IsCompleted = true; - BTFType.NameOff = BDebug.addString(Name); + switch (Kind) { + case BTF::BTF_KIND_PTR: + case BTF::BTF_KIND_CONST: + case BTF::BTF_KIND_VOLATILE: + case BTF::BTF_KIND_RESTRICT: + // Debug info might contain names for these types, but given that we want + // to keep BTF minimal and naming reference types doesn't bring any value + // (what matters is the completeness of the base type), we don't emit them. + // + // Furthermore, the Linux kernel refuses to load BPF programs that contain + // BTF with these types named: + // https://elixir.bootlin.com/linux/v6.17.1/source/kernel/bpf/btf.c#L2586 + BTFType.NameOff = 0; + break; + default: + BTFType.NameOff = BDebug.addString(Name); + break; + } if (NeedsFixup || !DTy) return; @@ -301,21 +320,59 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) { BTFType.NameOff = BDebug.addString(STy->getName()); + if (STy->getTag() == dwarf::DW_TAG_variant_part) { + // Variant parts might have a discriminator, which has its own memory + // location, and variants, which share the memory location afterwards. LLVM + // DI doesn't consider discriminator as an element and instead keeps + // it as a separate reference. + // To keep BTF simple, let's represent the structure as an union with + // discriminator as the first element. + // The offsets inside variant types are already handled correctly in the + // DI. + const auto *DTy = STy->getDiscriminator(); + if (DTy) { + struct BTF::BTFMember Discriminator; + + Discriminator.NameOff = BDebug.addString(DTy->getName()); + Discriminator.Offset = DTy->getOffsetInBits(); + const auto *BaseTy = DTy->getBaseType(); + Discriminator.Type = BDebug.getTypeId(BaseTy); + + Members.push_back(Discriminator); + } + } + // Add struct/union members. const DINodeArray Elements = STy->getElements(); for (const auto *Element : Elements) { struct BTF::BTFMember BTFMember; - const auto *DDTy = cast(Element); - BTFMember.NameOff = BDebug.addString(DDTy->getName()); - if (HasBitField) { - uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0; - BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits(); - } else { - BTFMember.Offset = DDTy->getOffsetInBits(); + switch (Element->getTag()) { + case dwarf::DW_TAG_member: { + const auto *DDTy = cast(Element); + + BTFMember.NameOff = BDebug.addString(DDTy->getName()); + if (HasBitField) { + uint8_t BitFieldSize = DDTy->isBitField() ? DDTy->getSizeInBits() : 0; + BTFMember.Offset = BitFieldSize << 24 | DDTy->getOffsetInBits(); + } else { + BTFMember.Offset = DDTy->getOffsetInBits(); + } + const auto *BaseTy = tryRemoveAtomicType(DDTy->getBaseType()); + BTFMember.Type = BDebug.getTypeId(BaseTy); + break; + } + case dwarf::DW_TAG_variant_part: { + const auto *DCTy = dyn_cast(Element); + + BTFMember.NameOff = BDebug.addString(DCTy->getName()); + BTFMember.Offset = DCTy->getOffsetInBits(); + BTFMember.Type = BDebug.getTypeId(DCTy); + break; + } + default: + llvm_unreachable("Unexpected DI tag of a struct/union element"); } - const auto *BaseTy = tryRemoveAtomicType(DDTy->getBaseType()); - BTFMember.Type = BDebug.getTypeId(BaseTy); Members.push_back(BTFMember); } } @@ -672,16 +729,28 @@ void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct, uint32_t &TypeId) { const DINodeArray Elements = CTy->getElements(); uint32_t VLen = Elements.size(); + // Variant parts might have a discriminator. LLVM DI doesn't consider it as + // an element and instead keeps it as a separate reference. But we represent + // it as an element in BTF. + if (CTy->getTag() == dwarf::DW_TAG_variant_part) { + const auto *DTy = CTy->getDiscriminator(); + if (DTy) { + visitTypeEntry(DTy); + VLen++; + } + } if (VLen > BTF::MAX_VLEN) return; // Check whether we have any bitfield members or not bool HasBitField = false; for (const auto *Element : Elements) { - auto E = cast(Element); - if (E->isBitField()) { - HasBitField = true; - break; + if (Element->getTag() == dwarf::DW_TAG_member) { + auto E = cast(Element); + if (E->isBitField()) { + HasBitField = true; + break; + } } } @@ -696,9 +765,22 @@ void BTFDebug::visitStructType(const DICompositeType *CTy, bool IsStruct, // Visit all struct members. int FieldNo = 0; for (const auto *Element : Elements) { - const auto Elem = cast(Element); - visitTypeEntry(Elem); - processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); + switch (Element->getTag()) { + case dwarf::DW_TAG_member: { + const auto Elem = cast(Element); + visitTypeEntry(Elem); + processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); + break; + } + case dwarf::DW_TAG_variant_part: { + const auto Elem = cast(Element); + visitTypeEntry(Elem); + processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); + break; + } + default: + llvm_unreachable("Unexpected DI tag of a struct/union element"); + } FieldNo++; } } @@ -781,16 +863,25 @@ void BTFDebug::visitFwdDeclType(const DICompositeType *CTy, bool IsUnion, void BTFDebug::visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId) { auto Tag = CTy->getTag(); - if (Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { + switch (Tag) { + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_variant_part: // Handle forward declaration differently as it does not have members. if (CTy->isForwardDecl()) visitFwdDeclType(CTy, Tag == dwarf::DW_TAG_union_type, TypeId); else visitStructType(CTy, Tag == dwarf::DW_TAG_structure_type, TypeId); - } else if (Tag == dwarf::DW_TAG_array_type) + break; + case dwarf::DW_TAG_array_type: visitArrayType(CTy, TypeId); - else if (Tag == dwarf::DW_TAG_enumeration_type) + break; + case dwarf::DW_TAG_enumeration_type: visitEnumType(CTy, TypeId); + break; + default: + llvm_unreachable("Unexpected DI tag of a composite type"); + } } bool BTFDebug::IsForwardDeclCandidate(const DIType *Base) { diff --git a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp index 5bd31707acb6f..c48cf5e6353ac 100644 --- a/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp +++ b/llvm/lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp @@ -43,12 +43,12 @@ namespace { class HexagonDisassembler : public MCDisassembler { public: std::unique_ptr const MCII; - std::unique_ptr CurrentBundle; + mutable std::unique_ptr CurrentBundle; mutable MCInst const *CurrentExtender; HexagonDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, MCInstrInfo const *MCII) - : MCDisassembler(STI, Ctx), MCII(MCII), CurrentBundle(new MCInst *), + : MCDisassembler(STI, Ctx), MCII(MCII), CurrentBundle(nullptr), CurrentExtender(nullptr) {} DecodeStatus getSingleInstruction(MCInst &Instr, MCInst &MCB, @@ -57,7 +57,27 @@ class HexagonDisassembler : public MCDisassembler { DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef Bytes, uint64_t Address, raw_ostream &CStream) const override; + + DecodeStatus getInstructionBundle(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &CStream) const override; + void remapInstruction(MCInst &Instr) const; + + Expected onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address) const override; + +private: + bool makeBundle(ArrayRef Bytes, uint64_t Address, + uint64_t &BytesToSkip, raw_ostream &CS) const; + + void resetBundle() const { + CurrentBundle.reset(); + CurrentInstruction = nullptr; + } + + mutable MCOperand *CurrentInstruction = nullptr; }; static uint64_t fullValue(HexagonDisassembler const &Disassembler, MCInst &MI, @@ -171,43 +191,88 @@ LLVMInitializeHexagonDisassembler() { createHexagonDisassembler); } -DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size, - ArrayRef Bytes, - uint64_t Address, - raw_ostream &CS) const { - CommentStream = &CS; - - DecodeStatus Result = DecodeStatus::Success; +bool HexagonDisassembler::makeBundle(ArrayRef Bytes, uint64_t Address, + uint64_t &BytesToSkip, + raw_ostream &CS) const { bool Complete = false; - Size = 0; + DecodeStatus Result = DecodeStatus::Success; - *CurrentBundle = &MI; - MI.setOpcode(Hexagon::BUNDLE); - MI.addOperand(MCOperand::createImm(0)); + CurrentBundle.reset(new MCInst); + CurrentBundle->setOpcode(Hexagon::BUNDLE); + CurrentBundle->addOperand(MCOperand::createImm(0)); while (Result == Success && !Complete) { if (Bytes.size() < HEXAGON_INSTR_SIZE) - return MCDisassembler::Fail; + return false; MCInst *Inst = getContext().createMCInst(); - Result = getSingleInstruction(*Inst, MI, Bytes, Address, CS, Complete); - MI.addOperand(MCOperand::createInst(Inst)); - Size += HEXAGON_INSTR_SIZE; + Result = getSingleInstruction(*Inst, *CurrentBundle, Bytes, Address, CS, + Complete); + CurrentBundle->addOperand(MCOperand::createInst(Inst)); + BytesToSkip += HEXAGON_INSTR_SIZE; Bytes = Bytes.slice(HEXAGON_INSTR_SIZE); } if (Result == MCDisassembler::Fail) - return Result; - if (Size > HEXAGON_MAX_PACKET_SIZE) - return MCDisassembler::Fail; + return false; + if (BytesToSkip > HEXAGON_MAX_PACKET_SIZE) + return false; const auto ArchSTI = Hexagon_MC::getArchSubtarget(&STI); const auto STI_ = (ArchSTI != nullptr) ? *ArchSTI : STI; - HexagonMCChecker Checker(getContext(), *MCII, STI_, MI, + HexagonMCChecker Checker(getContext(), *MCII, STI_, *CurrentBundle, *getContext().getRegisterInfo(), false); if (!Checker.check()) - return MCDisassembler::Fail; - remapInstruction(MI); + return false; + remapInstruction(*CurrentBundle); + return true; +} + +DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &CS) const { + CommentStream = &CS; + + Size = 0; + uint64_t BytesToSkip = 0; + + if (!CurrentBundle) { + if (!makeBundle(Bytes, Address, BytesToSkip, CS)) { + Size = BytesToSkip; + resetBundle(); + return MCDisassembler::Fail; + } + CurrentInstruction = (CurrentBundle->begin() + 1); + } + + MI = *(CurrentInstruction->getInst()); + Size = HEXAGON_INSTR_SIZE; + if (++CurrentInstruction == CurrentBundle->end()) + resetBundle(); return MCDisassembler::Success; } +DecodeStatus HexagonDisassembler::getInstructionBundle(MCInst &MI, + uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &CS) const { + CommentStream = &CS; + Size = 0; + uint64_t BytesToSkip = 0; + assert(!CurrentBundle); + + if (!makeBundle(Bytes, Address, BytesToSkip, CS)) { + Size = BytesToSkip; + resetBundle(); + return MCDisassembler::Fail; + } + + MI = *CurrentBundle; + Size = HEXAGON_INSTR_SIZE * HexagonMCInstrInfo::bundleSize(MI); + resetBundle(); + + return Success; +} + void HexagonDisassembler::remapInstruction(MCInst &Instr) const { for (auto I: HexagonMCInstrInfo::bundleInstructions(Instr)) { auto &MI = const_cast(*I.getInst()); @@ -465,6 +530,9 @@ DecodeStatus HexagonDisassembler::getSingleInstruction(MCInst &MI, MCInst &MCB, MI.insert(MI.begin() + 1, MCOperand::createExpr(MCConstantExpr::create(-1, getContext()))); break; + case Hexagon::Y4_crswap10: + MI.addOperand(MCOperand::createReg(Hexagon::SGP1_0)); + break; default: break; } @@ -482,7 +550,7 @@ DecodeStatus HexagonDisassembler::getSingleInstruction(MCInst &MI, MCInst &MCB, unsigned Offset = 1; bool Vector = HexagonMCInstrInfo::isVector(*MCII, MI); bool PrevVector = false; - auto Instructions = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle); + auto Instructions = HexagonMCInstrInfo::bundleInstructions(*CurrentBundle); auto i = Instructions.end() - 1; for (auto n = Instructions.begin() - 1;; --i, ++Offset) { if (i == n) @@ -540,6 +608,18 @@ DecodeStatus HexagonDisassembler::getSingleInstruction(MCInst &MI, MCInst &MCB, return Result; } +Expected HexagonDisassembler::onSymbolStart(SymbolInfoTy &Symbol, + uint64_t &Size, + ArrayRef Bytes, + uint64_t Address) const { + // At the start of a symbol, force a fresh packet by resetting any + // in-progress bundle state. This prevents packets from straddling label + // boundaries when data (e.g. jump tables) appears in between. + Size = 0; + resetBundle(); + return true; +} + static DecodeStatus DecodeRegisterClass(MCInst &Inst, unsigned RegNo, ArrayRef Table) { if (RegNo < Table.size()) { diff --git a/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp b/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp index a9201460d8e2e..2399e2a28eb22 100644 --- a/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp +++ b/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp @@ -921,6 +921,10 @@ void HexagonGenInsert::collectInBlock(MachineBasicBlock *B, // successors have been processed. RegisterSet BlockDefs, InsDefs; for (MachineInstr &MI : *B) { + // Stop if the map size is too large. + if (IFMap.size() >= MaxIFMSize) + break; + InsDefs.clear(); getInstrDefs(&MI, InsDefs); // Leave those alone. They are more transparent than "insert". @@ -943,8 +947,8 @@ void HexagonGenInsert::collectInBlock(MachineBasicBlock *B, findRecordInsertForms(VR, AVs); // Stop if the map size is too large. - if (IFMap.size() > MaxIFMSize) - return; + if (IFMap.size() >= MaxIFMSize) + break; } } diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 53943de3bc597..e285e04543694 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -1640,6 +1640,15 @@ bool HexagonDAGToDAGISel::DetectUseSxtw(SDValue &N, SDValue &R) { R = N; break; } + case ISD::AssertSext: { + EVT T = cast(N.getOperand(1))->getVT(); + if (T.getSizeInBits() == 32) + R = N.getOperand(0); + else + return false; + break; + } + default: return false; } diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index f1fa40c1b9036..48918fa00ae07 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -355,6 +355,8 @@ HexagonTargetLowering::initializeHVXLowering() { setCondCodeAction(ISD::SETULE, MVT::v64f16, Expand); setCondCodeAction(ISD::SETUGE, MVT::v64f16, Expand); setCondCodeAction(ISD::SETULT, MVT::v64f16, Expand); + setCondCodeAction(ISD::SETUO, MVT::v64f16, Expand); + setCondCodeAction(ISD::SETO, MVT::v64f16, Expand); setCondCodeAction(ISD::SETNE, MVT::v32f32, Expand); setCondCodeAction(ISD::SETLE, MVT::v32f32, Expand); @@ -368,6 +370,8 @@ HexagonTargetLowering::initializeHVXLowering() { setCondCodeAction(ISD::SETULE, MVT::v32f32, Expand); setCondCodeAction(ISD::SETUGE, MVT::v32f32, Expand); setCondCodeAction(ISD::SETULT, MVT::v32f32, Expand); + setCondCodeAction(ISD::SETUO, MVT::v32f32, Expand); + setCondCodeAction(ISD::SETO, MVT::v32f32, Expand); // Boolean vectors. diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 64bc5ca134c86..35863f790eae4 100644 --- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -2803,6 +2803,7 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset, case Hexagon::V6_vL32b_nt_cur_npred_ai: case Hexagon::V6_vL32b_nt_tmp_pred_ai: case Hexagon::V6_vL32b_nt_tmp_npred_ai: + case Hexagon::V6_vS32Ub_npred_ai: case Hexagon::V6_vgathermh_pseudo: case Hexagon::V6_vgathermw_pseudo: case Hexagon::V6_vgathermhw_pseudo: diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp index 9030e43b7149f..f83e06cd3d930 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp @@ -33,30 +33,18 @@ void HexagonInstPrinter::printRegName(raw_ostream &O, MCRegister Reg) { void HexagonInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &OS) { - assert(HexagonMCInstrInfo::isBundle(*MI)); - assert(HexagonMCInstrInfo::bundleSize(*MI) <= HEXAGON_PACKET_SIZE); - assert(HexagonMCInstrInfo::bundleSize(*MI) > 0); - HasExtender = false; - for (auto const &I : HexagonMCInstrInfo::bundleInstructions(*MI)) { - MCInst const &MCI = *I.getInst(); - if (HexagonMCInstrInfo::isDuplex(MII, MCI)) { - printInstruction(MCI.getOperand(1).getInst(), Address, OS); - OS << '\v'; - HasExtender = false; - printInstruction(MCI.getOperand(0).getInst(), Address, OS); - } else - printInstruction(&MCI, Address, OS); - HasExtender = HexagonMCInstrInfo::isImmext(MCI); - OS << "\n"; - } - - bool IsLoop0 = HexagonMCInstrInfo::isInnerLoop(*MI); - bool IsLoop1 = HexagonMCInstrInfo::isOuterLoop(*MI); - if (IsLoop0) { - OS << (IsLoop1 ? " :endloop01" : " :endloop0"); - } else if (IsLoop1) { - OS << " :endloop1"; + if (HexagonMCInstrInfo::isDuplex(MII, *MI)) { + printInstruction(MI->getOperand(1).getInst(), Address, OS); + OS << '\v'; + HasExtender = false; + printInstruction(MI->getOperand(0).getInst(), Address, OS); + } else { + printInstruction(MI, Address, OS); } + HasExtender = HexagonMCInstrInfo::isImmext(*MI); + if ((MI->getOpcode() & HexagonII::INST_PARSE_MASK) == + HexagonII::INST_PARSE_PACKET_END) + HasExtender = false; } void HexagonInstPrinter::printOperand(MCInst const *MI, unsigned OpNo, diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 980df819b2c26..bfea50e2d6dc0 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -252,8 +252,21 @@ class HexagonTargetAsmStreamer : public HexagonTargetStreamer { std::string Buffer; { raw_string_ostream TempStream(Buffer); - InstPrinter.printInst(&Inst, Address, "", STI, TempStream); + for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) { + InstPrinter.printInst(I.getInst(), Address, "", STI, TempStream); + TempStream << "\n"; + } + } + + std::string LoopString = ""; + bool IsLoop0 = HexagonMCInstrInfo::isInnerLoop(Inst); + bool IsLoop1 = HexagonMCInstrInfo::isOuterLoop(Inst); + if (IsLoop0) { + LoopString += (IsLoop1 ? " :endloop01" : " :endloop0"); + } else if (IsLoop1) { + LoopString += " :endloop1"; } + StringRef Contents(Buffer); auto PacketBundle = Contents.rsplit('\n'); auto HeadTail = PacketBundle.first.split('\n'); @@ -275,9 +288,9 @@ class HexagonTargetAsmStreamer : public HexagonTargetStreamer { } if (HexagonMCInstrInfo::isMemReorderDisabled(Inst)) - OS << "\n\t} :mem_noshuf" << PacketBundle.second; + OS << "\n\t} :mem_noshuf" << LoopString; else - OS << "\t}" << PacketBundle.second; + OS << "\t}" << LoopString; } void finish() override { finishAttributeSection(); } diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp index b757d123fa0ff..2ab2a98c9434c 100644 --- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp @@ -162,7 +162,7 @@ bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, else if (OffsetMO.isImm()) OS << ", " << OffsetMO.getImm(); else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() || - OffsetMO.isMCSymbol()) { + OffsetMO.isMCSymbol() || OffsetMO.isCPI()) { OS << ", "; MAI->printExpr(OS, *MCO.getExpr()); } else diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp index ac5e7f3891c72..1493bf4cba695 100644 --- a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp @@ -158,7 +158,12 @@ void LoongArchFrameLowering::processFunctionBeforeFrameFinalized( // estimateStackSize has been observed to under-estimate the final stack // size, so give ourselves wiggle-room by checking for stack size // representable an 11-bit signed field rather than 12-bits. - if (!isInt<11>(MFI.estimateStackSize(MF))) + // For [x]vstelm.{b/h/w/d} memory instructions with 8 imm offset, 7-bit + // signed field is fine. + unsigned EstimateStackSize = MFI.estimateStackSize(MF); + if (!isInt<11>(EstimateStackSize) || + (MF.getSubtarget().hasExtLSX() && + !isInt<7>(EstimateStackSize))) ScavSlotsNum = std::max(ScavSlotsNum, 1u); // For CFR spill. diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index c47987fbf683b..d6adcf37f06f9 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -2430,11 +2430,14 @@ static SDValue lowerBUILD_VECTORAsBroadCastLoad(BuildVectorSDNode *BVOp, } // make sure that this load is valid and only has one user. - if (!IdentitySrc || !BVOp->isOnlyUserOf(IdentitySrc.getNode())) + if (!IsIdeneity || !IdentitySrc || !BVOp->isOnlyUserOf(IdentitySrc.getNode())) return SDValue(); - if (IsIdeneity) { - auto *LN = cast(IdentitySrc); + auto *LN = cast(IdentitySrc); + auto ExtType = LN->getExtensionType(); + + if ((ExtType == ISD::EXTLOAD || ExtType == ISD::NON_EXTLOAD) && + VT.getScalarSizeInBits() == LN->getMemoryVT().getScalarSizeInBits()) { SDVTList Tys = LN->isIndexed() ? DAG.getVTList(VT, LN->getBasePtr().getValueType(), MVT::Other) @@ -4563,6 +4566,80 @@ static SDValue signExtendBitcastSrcVector(SelectionDAG &DAG, EVT SExtVT, llvm_unreachable("Unexpected node type for vXi1 sign extension"); } +static SDValue +performSETCC_BITCASTCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const LoongArchSubtarget &Subtarget) { + SDLoc DL(N); + EVT VT = N->getValueType(0); + SDValue Src = N->getOperand(0); + EVT SrcVT = Src.getValueType(); + + if (Src.getOpcode() != ISD::SETCC || !Src.hasOneUse()) + return SDValue(); + + bool UseLASX; + unsigned Opc = ISD::DELETED_NODE; + EVT CmpVT = Src.getOperand(0).getValueType(); + EVT EltVT = CmpVT.getVectorElementType(); + + if (Subtarget.hasExtLSX() && CmpVT.getSizeInBits() == 128) + UseLASX = false; + else if (Subtarget.has32S() && Subtarget.hasExtLASX() && + CmpVT.getSizeInBits() == 256) + UseLASX = true; + else + return SDValue(); + + SDValue SrcN1 = Src.getOperand(1); + switch (cast(Src.getOperand(2))->get()) { + default: + break; + case ISD::SETEQ: + // x == 0 => not (vmsknez.b x) + if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) + Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ; + break; + case ISD::SETGT: + // x > -1 => vmskgez.b x + if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) && EltVT == MVT::i8) + Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ; + break; + case ISD::SETGE: + // x >= 0 => vmskgez.b x + if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) + Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ; + break; + case ISD::SETLT: + // x < 0 => vmskltz.{b,h,w,d} x + if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && + (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 || + EltVT == MVT::i64)) + Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; + break; + case ISD::SETLE: + // x <= -1 => vmskltz.{b,h,w,d} x + if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) && + (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 || + EltVT == MVT::i64)) + Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; + break; + case ISD::SETNE: + // x != 0 => vmsknez.b x + if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) + Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ; + break; + } + + if (Opc == ISD::DELETED_NODE) + return SDValue(); + + SDValue V = DAG.getNode(Opc, DL, MVT::i64, Src.getOperand(0)); + EVT T = EVT::getIntegerVT(*DAG.getContext(), SrcVT.getVectorNumElements()); + V = DAG.getZExtOrTrunc(V, DL, T); + return DAG.getBitcast(VT, V); +} + static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const LoongArchSubtarget &Subtarget) { @@ -4577,110 +4654,63 @@ static SDValue performBITCASTCombine(SDNode *N, SelectionDAG &DAG, if (!SrcVT.isSimple() || SrcVT.getScalarType() != MVT::i1) return SDValue(); - unsigned Opc = ISD::DELETED_NODE; // Combine SETCC and BITCAST into [X]VMSK{LT,GE,NE} when possible + SDValue Res = performSETCC_BITCASTCombine(N, DAG, DCI, Subtarget); + if (Res) + return Res; + + // Generate vXi1 using [X]VMSKLTZ + MVT SExtVT; + unsigned Opc; + bool UseLASX = false; + bool PropagateSExt = false; + if (Src.getOpcode() == ISD::SETCC && Src.hasOneUse()) { - bool UseLASX; EVT CmpVT = Src.getOperand(0).getValueType(); - EVT EltVT = CmpVT.getVectorElementType(); - - if (Subtarget.hasExtLSX() && CmpVT.getSizeInBits() <= 128) - UseLASX = false; - else if (Subtarget.has32S() && Subtarget.hasExtLASX() && - CmpVT.getSizeInBits() <= 256) - UseLASX = true; - else + if (CmpVT.getSizeInBits() > 256) return SDValue(); - - SDValue SrcN1 = Src.getOperand(1); - switch (cast(Src.getOperand(2))->get()) { - default: - break; - case ISD::SETEQ: - // x == 0 => not (vmsknez.b x) - if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) - Opc = UseLASX ? LoongArchISD::XVMSKEQZ : LoongArchISD::VMSKEQZ; - break; - case ISD::SETGT: - // x > -1 => vmskgez.b x - if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) && EltVT == MVT::i8) - Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ; - break; - case ISD::SETGE: - // x >= 0 => vmskgez.b x - if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) - Opc = UseLASX ? LoongArchISD::XVMSKGEZ : LoongArchISD::VMSKGEZ; - break; - case ISD::SETLT: - // x < 0 => vmskltz.{b,h,w,d} x - if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && - (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 || - EltVT == MVT::i64)) - Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; - break; - case ISD::SETLE: - // x <= -1 => vmskltz.{b,h,w,d} x - if (ISD::isBuildVectorAllOnes(SrcN1.getNode()) && - (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 || - EltVT == MVT::i64)) - Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; - break; - case ISD::SETNE: - // x != 0 => vmsknez.b x - if (ISD::isBuildVectorAllZeros(SrcN1.getNode()) && EltVT == MVT::i8) - Opc = UseLASX ? LoongArchISD::XVMSKNEZ : LoongArchISD::VMSKNEZ; - break; - } } - // Generate vXi1 using [X]VMSKLTZ - if (Opc == ISD::DELETED_NODE) { - MVT SExtVT; - bool UseLASX = false; - bool PropagateSExt = false; - switch (SrcVT.getSimpleVT().SimpleTy) { - default: - return SDValue(); - case MVT::v2i1: - SExtVT = MVT::v2i64; - break; - case MVT::v4i1: - SExtVT = MVT::v4i32; - if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { - SExtVT = MVT::v4i64; - UseLASX = true; - PropagateSExt = true; - } - break; - case MVT::v8i1: - SExtVT = MVT::v8i16; - if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { - SExtVT = MVT::v8i32; - UseLASX = true; - PropagateSExt = true; - } - break; - case MVT::v16i1: - SExtVT = MVT::v16i8; - if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { - SExtVT = MVT::v16i16; - UseLASX = true; - PropagateSExt = true; - } - break; - case MVT::v32i1: - SExtVT = MVT::v32i8; + switch (SrcVT.getSimpleVT().SimpleTy) { + default: + return SDValue(); + case MVT::v2i1: + SExtVT = MVT::v2i64; + break; + case MVT::v4i1: + SExtVT = MVT::v4i32; + if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { + SExtVT = MVT::v4i64; UseLASX = true; - break; - }; - if (UseLASX && !Subtarget.has32S() && !Subtarget.hasExtLASX()) - return SDValue(); - Src = PropagateSExt ? signExtendBitcastSrcVector(DAG, SExtVT, Src, DL) - : DAG.getNode(ISD::SIGN_EXTEND, DL, SExtVT, Src); - Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; - } else { - Src = Src.getOperand(0); - } + PropagateSExt = true; + } + break; + case MVT::v8i1: + SExtVT = MVT::v8i16; + if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { + SExtVT = MVT::v8i32; + UseLASX = true; + PropagateSExt = true; + } + break; + case MVT::v16i1: + SExtVT = MVT::v16i8; + if (Subtarget.hasExtLASX() && checkBitcastSrcVectorSize(Src, 256, 0)) { + SExtVT = MVT::v16i16; + UseLASX = true; + PropagateSExt = true; + } + break; + case MVT::v32i1: + SExtVT = MVT::v32i8; + UseLASX = true; + break; + }; + if (UseLASX && !(Subtarget.has32S() && Subtarget.hasExtLASX())) + return SDValue(); + Src = PropagateSExt ? signExtendBitcastSrcVector(DAG, SExtVT, Src, DL) + : DAG.getNode(ISD::SIGN_EXTEND, DL, SExtVT, Src); + Opc = UseLASX ? LoongArchISD::XVMSKLTZ : LoongArchISD::VMSKLTZ; SDValue V = DAG.getNode(Opc, DL, MVT::i64, Src); EVT T = EVT::getIntegerVT(*DAG.getContext(), SrcVT.getVectorNumElements()); diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index 26d36f1c5058f..75a230268bf58 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -378,12 +378,9 @@ bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp, } } -bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, - const MachineBasicBlock *MBB, - const MachineFunction &MF) const { - if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF)) - return true; - +bool LoongArchInstrInfo::isSafeToMove(const MachineInstr &MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const { auto MII = MI.getIterator(); auto MIE = MBB->end(); @@ -429,25 +426,25 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, auto MO2 = Lu32I->getOperand(2).getTargetFlags(); if (MO0 == LoongArchII::MO_PCREL_HI && MO1 == LoongArchII::MO_PCREL_LO && MO2 == LoongArchII::MO_PCREL64_LO) - return true; + return false; if ((MO0 == LoongArchII::MO_GOT_PC_HI || MO0 == LoongArchII::MO_LD_PC_HI || MO0 == LoongArchII::MO_GD_PC_HI) && MO1 == LoongArchII::MO_GOT_PC_LO && MO2 == LoongArchII::MO_GOT_PC64_LO) - return true; + return false; if (MO0 == LoongArchII::MO_IE_PC_HI && MO1 == LoongArchII::MO_IE_PC_LO && MO2 == LoongArchII::MO_IE_PC64_LO) - return true; + return false; if (MO0 == LoongArchII::MO_DESC_PC_HI && MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC64_PC_LO) - return true; + return false; break; } case LoongArch::LU52I_D: { auto MO = MI.getOperand(2).getTargetFlags(); if (MO == LoongArchII::MO_PCREL64_HI || MO == LoongArchII::MO_GOT_PC64_HI || MO == LoongArchII::MO_IE_PC64_HI || MO == LoongArchII::MO_DESC64_PC_HI) - return true; + return false; break; } default: @@ -487,7 +484,7 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2)); if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD) - return true; + return false; break; } if (SecondOp == MIE || @@ -496,34 +493,34 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_PCREL_LO) - return true; + return false; if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp && MO1 == LoongArchII::MO_GOT_PC_LO) - return true; + return false; if ((MO0 == LoongArchII::MO_LD_PC_HI || MO0 == LoongArchII::MO_GD_PC_HI) && SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO) - return true; + return false; break; } case LoongArch::ADDI_W: case LoongArch::ADDI_D: { auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO) - return true; + return false; break; } case LoongArch::LD_W: case LoongArch::LD_D: { auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); if (MO == LoongArchII::MO_GOT_PC_LO) - return true; + return false; break; } case LoongArch::PseudoDESC_CALL: { auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); if (MO == LoongArchII::MO_DESC_CALL) - return true; + return false; break; } default: @@ -531,6 +528,18 @@ bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, } } + return true; +} + +bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const { + if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF)) + return true; + + if (!isSafeToMove(MI, MBB, MF)) + return true; + return false; } diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h index 63b7112b8b40a..282ea30b03299 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h @@ -64,6 +64,9 @@ class LoongArchInstrInfo : public LoongArchGenInstrInfo { bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override; + bool isSafeToMove(const MachineInstr &MI, const MachineBasicBlock *MBB, + const MachineFunction &MF) const override; + bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp index f62753356a4dd..a2292d016efa1 100644 --- a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp @@ -759,6 +759,10 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20, MO.ChangeToBA(ImmOp.getBlockAddress(), ImmOp.getOffset(), LoongArchII::getDirectFlags(ImmOp)); break; + case MachineOperand::MO_ConstantPoolIndex: + MO.ChangeToCPI(ImmOp.getIndex(), ImmOp.getOffset(), + LoongArchII::getDirectFlags(ImmOp)); + break; default: report_fatal_error("unsupported machine operand type"); break; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp index 03ce004ed33a5..7cefb3f8119b8 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp @@ -52,6 +52,9 @@ static ABI getTripleABI(const Triple &TT) { bool Is64Bit = TT.isArch64Bit(); ABI TripleABI; switch (TT.getEnvironment()) { + case llvm::Triple::EnvironmentType::UnknownEnvironment: + TripleABI = ABI_Unknown; + break; case llvm::Triple::EnvironmentType::GNUSF: case llvm::Triple::EnvironmentType::MuslSF: TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S; @@ -96,7 +99,7 @@ ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, // 1. If the '-target-abi' is valid, use it. if (IsABIValidForFeature(ArgProvidedABI)) { - if (TT.hasEnvironment() && ArgProvidedABI != TripleABI) + if (IsABIValidForFeature(TripleABI) && ArgProvidedABI != TripleABI) errs() << "warning: triple-implied ABI conflicts with provided target-abi '" << ABIName << "', using target-abi\n"; @@ -164,10 +167,7 @@ ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, return Is64Bit ? ABI_LP64F : ABI_ILP32F; return Is64Bit ? ABI_LP64S : ABI_ILP32S; }; - if (ABIName.empty()) - errs() << "warning: the triple-implied ABI is invalid, ignoring and using " - "feature-implied ABI\n"; - else + if (!ABIName.empty()) errs() << "warning: both target-abi and the triple-implied ABI are " "invalid, ignoring and using feature-implied ABI\n"; return checkABIStandardized(GetFeatureABI()); diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 01e4d17f6236d..602b89a117595 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3676,7 +3676,7 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, Out, STI)) return true; - if (IsLikely) { + if (IsLikely && MemOffsetOp.isExpr()) { TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MCOperand::createExpr(MemOffsetOp.getExpr()), IDLoc, STI); TOut.emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 87e06a6d3c08a..2903ff75475cf 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -747,14 +747,18 @@ void MipsAsmPrinter::emitStartOfAsmFile(Module &M) { if (FS.empty() && M.size() && F->hasFnAttribute("target-features")) FS = F->getFnAttribute("target-features").getValueAsString(); + std::string strFS = FS.str(); + if (M.size() && F->getFnAttribute("use-soft-float").getValueAsBool()) + strFS += strFS.empty() ? "+soft-float" : ",+soft-float"; + // Compute MIPS architecture attributes based on the default subtarget // that we'd have constructed. // FIXME: For ifunc related functions we could iterate over and look // for a feature string that doesn't match the default one. StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU()); const MipsTargetMachine &MTM = static_cast(TM); - const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, - std::nullopt); + const MipsSubtarget STI(TT, CPU, StringRef(strFS), MTM.isLittleEndian(), + MTM, std::nullopt); bool IsABICalls = STI.isABICalls(); const MipsABIInfo &ABI = MTM.getABI(); diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp index 34ff41f6e02da..78f2e5db40f9d 100644 --- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -432,13 +432,24 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( Register OldVal = I->getOperand(6).getReg(); Register BinOpRes = I->getOperand(7).getReg(); Register StoreVal = I->getOperand(8).getReg(); + bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32(); const BasicBlock *LLVM_BB = BB.getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop1MBB = nullptr; + MachineBasicBlock *loop2MBB = nullptr; + if (NoMovnInstr) { + loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); + loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + } MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = ++BB.getIterator(); MF->insert(It, loopMBB); + if (NoMovnInstr) { + MF->insert(It, loop1MBB); + MF->insert(It, loop2MBB); + } MF->insert(It, sinkMBB); MF->insert(It, exitMBB); @@ -446,9 +457,19 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( exitMBB->transferSuccessorsAndUpdatePHIs(&BB); BB.addSuccessor(loopMBB, BranchProbability::getOne()); - loopMBB->addSuccessor(sinkMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->normalizeSuccProbs(); + if (NoMovnInstr) { + loopMBB->addSuccessor(loop1MBB); + loopMBB->addSuccessor(loop2MBB); + } else { + loopMBB->addSuccessor(sinkMBB); + loopMBB->addSuccessor(loopMBB); + loopMBB->normalizeSuccProbs(); + } + if (NoMovnInstr) { + loop1MBB->addSuccessor(loop2MBB); + loop2MBB->addSuccessor(loopMBB); + loop2MBB->addSuccessor(sinkMBB); + } BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); if (IsNand) { @@ -525,7 +546,7 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) .addReg(BinOpRes) .addReg(Scratch4); - } else { + } else if (STI->hasMips4() || STI->hasMips32()) { // max: move BinOpRes, StoreVal // movn BinOpRes, Incr, Scratch4, BinOpRes // min: move BinOpRes, StoreVal @@ -537,12 +558,59 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( .addReg(Incr) .addReg(Scratch4) .addReg(BinOpRes); + } else { + // if min: + // loopMBB: move BinOpRes, StoreVal + // beq Scratch4, 0, loop1MBB + // j loop2MBB + // loop1MBB: move BinOpRes, Incr + // loop2MBB: and BinOpRes, BinOpRes, Mask + // and StoreVal, OlddVal, Mask2 + // or StoreVal, StoreVal, BinOpRes + // StoreVal = sc StoreVal, 0(Ptr) + // beq StoreVal, zero, loopMBB + // + // if max: + // loopMBB: move BinOpRes, Incr + // beq Scratch4, 0, loop1MBB + // j loop2MBB + // loop1MBB: move BinOpRes, StoreVal + // loop2MBB: and BinOpRes, BinOpRes, Mask + // and StoreVal, OlddVal, Mask2 + // or StoreVal, StoreVal, BinOpRes + // StoreVal = sc StoreVal, 0(Ptr) + // beq StoreVal, zero, loopMBB + if (IsMin) { + BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) + .addReg(StoreVal) + .addReg(Mips::ZERO); + BuildMI(loop1MBB, DL, TII->get(OR), BinOpRes) + .addReg(Incr) + .addReg(Mips::ZERO); + } else { + BuildMI(loopMBB, DL, TII->get(OR), BinOpRes) + .addReg(Incr) + .addReg(Mips::ZERO); + BuildMI(loop1MBB, DL, TII->get(OR), BinOpRes) + .addReg(StoreVal) + .addReg(Mips::ZERO); + } + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(Scratch4) + .addReg(Mips::ZERO) + .addMBB(loop1MBB); + BuildMI(loopMBB, DL, TII->get(Mips::J)).addMBB(loop2MBB); } // and BinOpRes, BinOpRes, Mask - BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) - .addReg(BinOpRes) - .addReg(Mask); + if (NoMovnInstr) + BuildMI(loop2MBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(BinOpRes) + .addReg(Mask); + else + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(BinOpRes) + .addReg(Mask); } else if (!IsSwap) { // binopres, oldval, incr2 @@ -564,14 +632,37 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( // or StoreVal, StoreVal, BinOpRes // StoreVal = sc StoreVal, 0(Ptr) // beq StoreVal, zero, loopMBB - BuildMI(loopMBB, DL, TII->get(Mips::AND), StoreVal) - .addReg(OldVal).addReg(Mask2); - BuildMI(loopMBB, DL, TII->get(Mips::OR), StoreVal) - .addReg(StoreVal).addReg(BinOpRes); - BuildMI(loopMBB, DL, TII->get(SC), StoreVal) - .addReg(StoreVal).addReg(Ptr).addImm(0); - BuildMI(loopMBB, DL, TII->get(BEQ)) - .addReg(StoreVal).addReg(Mips::ZERO).addMBB(loopMBB); + if (NoMovnInstr) { + BuildMI(loop2MBB, DL, TII->get(Mips::AND), StoreVal) + .addReg(OldVal) + .addReg(Mask2); + BuildMI(loop2MBB, DL, TII->get(Mips::OR), StoreVal) + .addReg(StoreVal) + .addReg(BinOpRes); + BuildMI(loop2MBB, DL, TII->get(SC), StoreVal) + .addReg(StoreVal) + .addReg(Ptr) + .addImm(0); + BuildMI(loop2MBB, DL, TII->get(BEQ)) + .addReg(StoreVal) + .addReg(Mips::ZERO) + .addMBB(loopMBB); + } else { + BuildMI(loopMBB, DL, TII->get(Mips::AND), StoreVal) + .addReg(OldVal) + .addReg(Mask2); + BuildMI(loopMBB, DL, TII->get(Mips::OR), StoreVal) + .addReg(StoreVal) + .addReg(BinOpRes); + BuildMI(loopMBB, DL, TII->get(SC), StoreVal) + .addReg(StoreVal) + .addReg(Ptr) + .addImm(0); + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(StoreVal) + .addReg(Mips::ZERO) + .addMBB(loopMBB); + } // sinkMBB: // and maskedoldval1,oldval,mask @@ -600,6 +691,11 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( LivePhysRegs LiveRegs; computeAndAddLiveIns(LiveRegs, *loopMBB); + if (loop1MBB) { + assert(loop2MBB && "should have 2 loop blocks"); + computeAndAddLiveIns(LiveRegs, *loop1MBB); + computeAndAddLiveIns(LiveRegs, *loop2MBB); + } computeAndAddLiveIns(LiveRegs, *sinkMBB); computeAndAddLiveIns(LiveRegs, *exitMBB); @@ -746,20 +842,41 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, llvm_unreachable("Unknown pseudo atomic!"); } + bool NoMovnInstr = (IsMin || IsMax) && !STI->hasMips4() && !STI->hasMips32(); const BasicBlock *LLVM_BB = BB.getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop1MBB = nullptr; + MachineBasicBlock *loop2MBB = nullptr; + if (NoMovnInstr) { + loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); + loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + } MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = ++BB.getIterator(); MF->insert(It, loopMBB); + if (NoMovnInstr) { + MF->insert(It, loop1MBB); + MF->insert(It, loop2MBB); + } MF->insert(It, exitMBB); exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); exitMBB->transferSuccessorsAndUpdatePHIs(&BB); BB.addSuccessor(loopMBB, BranchProbability::getOne()); - loopMBB->addSuccessor(exitMBB); - loopMBB->addSuccessor(loopMBB); + if (NoMovnInstr) { + loopMBB->addSuccessor(loop1MBB); + loopMBB->addSuccessor(loop2MBB); + } else { + loopMBB->addSuccessor(exitMBB); + loopMBB->addSuccessor(loopMBB); + } loopMBB->normalizeSuccProbs(); + if (NoMovnInstr) { + loop1MBB->addSuccessor(loop2MBB); + loop2MBB->addSuccessor(loopMBB); + loop2MBB->addSuccessor(exitMBB); + } BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); @@ -802,7 +919,7 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, BuildMI(loopMBB, DL, TII->get(OR), Scratch) .addReg(Scratch) .addReg(Scratch2); - } else { + } else if (STI->hasMips4() || STI->hasMips32()) { // max: move Scratch, OldVal // movn Scratch, Incr, Scratch2, Scratch // min: move Scratch, OldVal @@ -814,6 +931,38 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, .addReg(Incr) .addReg(Scratch2) .addReg(Scratch); + } else { + // if min: + // loopMBB: move Scratch, OldVal + // beq Scratch2_32, 0, loop1MBB + // j loop2MBB + // loop1MBB: move Scratch, Incr + // loop2MBB: sc $2, 0($4) + // beqz $2, $BB0_1 + // nop + // + // if max: + // loopMBB: move Scratch, Incr + // beq Scratch2_32, 0, loop1MBB + // j loop2MBB + // loop1MBB: move Scratch, OldVal + // loop2MBB: sc $2, 0($4) + // beqz $2, $BB0_1 + // nop + if (IsMin) { + BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(OldVal).addReg(ZERO); + BuildMI(loop1MBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); + } else { + BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); + BuildMI(loop1MBB, DL, TII->get(OR), Scratch) + .addReg(OldVal) + .addReg(ZERO); + } + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(Scratch2_32) + .addReg(ZERO) + .addMBB(loop1MBB); + BuildMI(loopMBB, DL, TII->get(Mips::J)).addMBB(loop2MBB); } } else if (Opcode) { @@ -829,20 +978,36 @@ bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); } - BuildMI(loopMBB, DL, TII->get(SC), Scratch) - .addReg(Scratch) - .addReg(Ptr) - .addImm(0); - BuildMI(loopMBB, DL, TII->get(BEQ)) - .addReg(Scratch) - .addReg(ZERO) - .addMBB(loopMBB); + if (NoMovnInstr) { + BuildMI(loop2MBB, DL, TII->get(SC), Scratch) + .addReg(Scratch) + .addReg(Ptr) + .addImm(0); + BuildMI(loop2MBB, DL, TII->get(BEQ)) + .addReg(Scratch) + .addReg(ZERO) + .addMBB(loopMBB); + } else { + BuildMI(loopMBB, DL, TII->get(SC), Scratch) + .addReg(Scratch) + .addReg(Ptr) + .addImm(0); + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(Scratch) + .addReg(ZERO) + .addMBB(loopMBB); + } NMBBI = BB.end(); I->eraseFromParent(); LivePhysRegs LiveRegs; computeAndAddLiveIns(LiveRegs, *loopMBB); + if (loop1MBB) { + assert(loop2MBB && "should have 2 loop blocks"); + computeAndAddLiveIns(LiveRegs, *loop1MBB); + computeAndAddLiveIns(LiveRegs, *loop2MBB); + } computeAndAddLiveIns(LiveRegs, *exitMBB); return true; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 0e581a7a16503..ec6b382151660 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -522,9 +522,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::TRAP, MVT::Other, Legal); - setOperationAction(ISD::ConstantFP, MVT::f32, Custom); - setOperationAction(ISD::ConstantFP, MVT::f64, Custom); - setTargetDAGCombine({ISD::SDIVREM, ISD::UDIVREM, ISD::SELECT, ISD::AND, ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL, ISD::SIGN_EXTEND}); @@ -1360,8 +1357,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::FP_TO_SINT: return lowerFP_TO_SINT(Op, DAG); case ISD::READCYCLECOUNTER: return lowerREADCYCLECOUNTER(Op, DAG); - case ISD::ConstantFP: - return lowerConstantFP(Op, DAG); } return SDValue(); } @@ -3019,30 +3014,6 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, return DAG.getNode(ISD::BITCAST, SDLoc(Op), Op.getValueType(), Trunc); } -SDValue MipsTargetLowering::lowerConstantFP(SDValue Op, - SelectionDAG &DAG) const { - SDLoc DL(Op); - EVT VT = Op.getSimpleValueType(); - SDNode *N = Op.getNode(); - ConstantFPSDNode *CFP = cast(N); - - if (!CFP->isNaN() || Subtarget.isNaN2008()) { - return SDValue(); - } - - APFloat NaNValue = CFP->getValueAPF(); - auto &Sem = NaNValue.getSemantics(); - - // The MSB of the mantissa should be zero for QNaNs in the MIPS legacy NaN - // encodings, and one for sNaNs. Check every NaN constants and make sure - // they are correctly encoded for legacy encodings. - if (!NaNValue.isSignaling()) { - APFloat RealQNaN = NaNValue.getSNaN(Sem); - return DAG.getConstantFP(RealQNaN, DL, VT); - } - return SDValue(); -} - //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 31ac5d4c185bc..c65c76ccffc75 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -592,7 +592,6 @@ class TargetRegisterClass; SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const; /// isEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index b6125b972717a..255fd838a72a2 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -858,6 +858,16 @@ def calltarget : Operand { def imm64: Operand; +def ConstantImmAsmOperandClass : AsmOperandClass { + let Name = "ConstantImm"; + let PredicateMethod = "isConstantImm"; + let RenderMethod = "addImmOperands"; +} + +def ConstantImm64: Operand { + let ParserMatchClass = ConstantImmAsmOperandClass; +} + def simm19_lsl2 : Operand { let EncoderMethod = "getSimm19Lsl2Encoding"; let DecoderMethod = "DecodeSimm19Lsl2"; @@ -2950,10 +2960,10 @@ def : MipsInstAlias<"nor\t$rs, $imm", (NORImm GPR32Opnd:$rs, GPR32Opnd:$rs, let hasDelaySlot = 1, isCTI = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins imm64:$imm64, brtarget:$offset), + (ins ConstantImm64:$imm64, brtarget:$offset), "bne\t$rt, $imm64, $offset">; def BeqImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), - (ins imm64:$imm64, brtarget:$offset), + (ins ConstantImm64:$imm64, brtarget:$offset), "beq\t$rt, $imm64, $offset">; class CondBranchPseudo : @@ -2981,7 +2991,7 @@ def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; let isCTI = 1 in class CondBranchImmPseudo : - MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), + MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, ConstantImm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; def BEQLImmMacro : CondBranchImmPseudo<"beql">, ISA_MIPS2_NOT_32R6_64R6; diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index 14f05250ad6b8..5d496f69172c3 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -5008,12 +5008,6 @@ combineUnpackingMovIntoLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { return !U.getUser()->use_empty(); } - // Handle CopyToReg nodes that will become dead after our replacement - if (U.getUser()->getOpcode() == ISD::CopyToReg) { - DeadCopyToRegs.push_back(U.getUser()); - return true; - } - // Otherwise, this use prevents us from splitting a value. return false; })) @@ -5080,10 +5074,6 @@ combineUnpackingMovIntoLoad(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { for (unsigned I : seq(NewLoad->getNumValues() - NewNumOutputs)) Results.push_back(NewLoad.getValue(NewNumOutputs + I)); - // Remove dead CopyToReg nodes by folding them into the chain they reference - for (SDNode *CTR : DeadCopyToRegs) - DCI.CombineTo(CTR, CTR->getOperand(0)); - return DCI.DAG.getMergeValues(Results, DL); } @@ -6418,4 +6408,4 @@ void NVPTXTargetLowering::computeKnownBitsForTargetNode( default: break; } -} \ No newline at end of file +} diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h index 9a6e261c811a0..437edfb8ffc75 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h +++ b/llvm/lib/Target/NVPTX/NVPTXTargetTransformInfo.h @@ -183,6 +183,11 @@ class NVPTXTTIImpl final : public BasicTTIImplBase { void collectKernelLaunchBounds( const Function &F, SmallVectorImpl> &LB) const override; + + bool shouldBuildRelLookupTables() const override { + // Self-referential globals are not supported. + return false; + } }; } // end namespace llvm diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 459525ed4ee9a..b6db0abcc86d0 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -7296,9 +7296,17 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX( if (!ArgVT.isVector() && !ValVT.isVector() && ArgVT.isInteger() && ValVT.isInteger() && ArgVT.getScalarSizeInBits() < ValVT.getScalarSizeInBits()) { - SDValue ArgValueTrunc = DAG.getNode( - ISD::TRUNCATE, dl, ArgVT.getSimpleVT() == MVT::i1 ? MVT::i8 : ArgVT, - ArgValue); + // It is possible to have either real integer values + // or integers that were not originally integers. + // In the latter case, these could have came from structs, + // and these integers would not have an extend on the parameter. + // Since these types of integers do not have an extend specified + // in the first place, the type of extend that we do should not matter. + EVT TruncatedArgVT = ArgVT.isSimple() && ArgVT.getSimpleVT() == MVT::i1 + ? MVT::i8 + : ArgVT; + SDValue ArgValueTrunc = + DAG.getNode(ISD::TRUNCATE, dl, TruncatedArgVT, ArgValue); SDValue ArgValueExt = ArgSignExt ? DAG.getSExtOrTrunc(ArgValueTrunc, dl, ValVT) : DAG.getZExtOrTrunc(ArgValueTrunc, dl, ValVT); @@ -9586,12 +9594,14 @@ static bool isValidSplatLoad(const PPCSubtarget &Subtarget, const SDValue &Op, return false; } -bool isValidMtVsrBmi(APInt &BitMask, BuildVectorSDNode &BVN) { +bool isValidMtVsrBmi(APInt &BitMask, BuildVectorSDNode &BVN, + bool IsLittleEndian) { assert(BVN.getNumOperands() > 0 && "Unexpected 0-size build vector"); BitMask.clearAllBits(); EVT VT = BVN.getValueType(0); - APInt ConstValue(VT.getSizeInBits(), 0); + unsigned VTSize = VT.getSizeInBits(); + APInt ConstValue(VTSize, 0); unsigned EltWidth = VT.getScalarSizeInBits(); @@ -9601,8 +9611,10 @@ bool isValidMtVsrBmi(APInt &BitMask, BuildVectorSDNode &BVN) { if (!CN) return false; - - ConstValue.insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth), BitPos); + // The elements in a vector register are ordered in reverse byte order + // between little-endian and big-endian modes. + ConstValue.insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth), + IsLittleEndian ? BitPos : VTSize - EltWidth - BitPos); BitPos += EltWidth; } @@ -9633,7 +9645,8 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, // we do not convert it to MTVSRBMI. // The xxleqv instruction sets a vector with all ones. // The xxlxor instruction sets a vector with all zeros. - if (isValidMtVsrBmi(BitMask, *BVN) && BitMask != 0 && BitMask != 0xffff) { + if (isValidMtVsrBmi(BitMask, *BVN, Subtarget.isLittleEndian()) && + BitMask != 0 && BitMask != 0xffff) { SDValue SDConstant = DAG.getTargetConstant(BitMask, dl, MVT::i32); MachineSDNode *MSDNode = DAG.getMachineNode(PPC::MTVSRBMI, dl, MVT::v16i8, SDConstant); @@ -15314,6 +15327,12 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, } } + // Convert PromOps to handles before doing any RAUW operations, as these + // may CSE with existing nodes, deleting the originals. + std::list PromOpHandles; + for (auto &PromOp : PromOps) + PromOpHandles.emplace_back(PromOp); + // Replace all inputs, either with the truncation operand, or a // truncation or extension to the final output type. for (unsigned i = 0, ie = Inputs.size(); i != ie; ++i) { @@ -15337,10 +15356,6 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, DAG.getAnyExtOrTrunc(InSrc, dl, N->getValueType(0))); } - std::list PromOpHandles; - for (auto &PromOp : PromOps) - PromOpHandles.emplace_back(PromOp); - // Replace all operations (these are all the same, but have a different // (promoted) return type). DAG.getNode will validate that the types of // a binary operator match, so go through the list in reverse so that diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 99ef89a7fdc0c..dbbf06f471533 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3252,7 +3252,8 @@ def PPC32GOT: PPCEmitTimePseudo<(outs gprc:$rD), (ins), "#PPC32GOT", // Get the _GLOBAL_OFFSET_TABLE_ in PIC mode. // This uses two output registers, the first as the real output, the second as a -// temporary register, used internally in code generation. +// temporary register, used internally in code generation. A "bl" also clobbers LR. +let Defs = [LR] in def PPC32PICGOT: PPCEmitTimePseudo<(outs gprc:$rD, gprc:$rT), (ins), "#PPC32PICGOT", []>, NoEncode<"$rT">; diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index 76dca4794e050..f1230407b1649 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -1102,13 +1102,20 @@ void PPCRegisterInfo::lowerCRBitSpilling(MachineBasicBlock::iterator II, SpillsKnownBit = true; break; default: + // When spilling a CR bit, the super register may not be explicitly defined + // (i.e. it can be defined by a CR-logical that only defines the subreg) so + // we state that the CR field is undef. Also, in order to preserve the kill + // flag on the CR bit, we add it as an implicit use. + // On Power10, we can use SETNBC to spill all CR bits. SETNBC will set all // bits (specifically, it produces a -1 if the CR bit is set). Ultimately, // the bit that is of importance to us is bit 32 (bit 0 of a 32-bit // register), and SETNBC will set this. if (Subtarget.isISA3_1()) { BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::SETNBC8 : PPC::SETNBC), Reg) - .addReg(SrcReg, RegState::Undef); + .addReg(SrcReg, RegState::Undef) + .addReg(SrcReg, RegState::Implicit | + getKillRegState(MI.getOperand(0).isKill())); break; } @@ -1122,16 +1129,14 @@ void PPCRegisterInfo::lowerCRBitSpilling(MachineBasicBlock::iterator II, SrcReg == PPC::CR4LT || SrcReg == PPC::CR5LT || SrcReg == PPC::CR6LT || SrcReg == PPC::CR7LT) { BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::SETB8 : PPC::SETB), Reg) - .addReg(getCRFromCRBit(SrcReg), RegState::Undef); + .addReg(getCRFromCRBit(SrcReg), RegState::Undef) + .addReg(SrcReg, RegState::Implicit | + getKillRegState(MI.getOperand(0).isKill())); break; } } // We need to move the CR field that contains the CR bit we are spilling. - // The super register may not be explicitly defined (i.e. it can be defined - // by a CR-logical that only defines the subreg) so we state that the CR - // field is undef. Also, in order to preserve the kill flag on the CR bit, - // we add it as an implicit use. BuildMI(MBB, II, dl, TII.get(LP64 ? PPC::MFOCRF8 : PPC::MFOCRF), Reg) .addReg(getCRFromCRBit(SrcReg), RegState::Undef) .addReg(SrcReg, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index e42d6c539a349..df3028e051399 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -792,6 +792,23 @@ void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F, Asm->getWriter().recordRelocation(F, VendorFixup, VendorTarget, VendorValue); } +static bool relaxableFixupNeedsRelocation(const MCFixupKind Kind) { + // Some Fixups are marked as LinkerRelaxable by + // `RISCVMCCodeEmitter::getImmOpValue` only because they may be + // (assembly-)relaxed into a linker-relaxable instruction. This function + // should return `false` for those fixups so they do not get a `R_RISCV_RELAX` + // relocation emitted in addition to the relocation. + switch (Kind) { + default: + break; + case RISCV::fixup_riscv_rvc_jump: + case RISCV::fixup_riscv_rvc_branch: + case RISCV::fixup_riscv_jal: + return false; + } + return true; +} + bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup, const MCValue &Target, uint64_t &FixedValue, bool IsResolved) { @@ -834,25 +851,32 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup, return false; } - // If linker relaxation is enabled and supported by the current relocation, - // generate a relocation and then append a RELAX. - if (Fixup.isLinkerRelaxable()) + // If linker relaxation is enabled and supported by the current fixup, then we + // always want to generate a relocation. + bool NeedsRelax = Fixup.isLinkerRelaxable() && + relaxableFixupNeedsRelocation(Fixup.getKind()); + if (NeedsRelax) IsResolved = false; + if (IsResolved && Fixup.isPCRel()) IsResolved = isPCRelFixupResolved(Target.getAddSym(), F); if (!IsResolved) { - // Some Fixups require a vendor relocation, record it (directly) before we + // Some Fixups require a VENDOR relocation, record it (directly) before we // add the relocation. maybeAddVendorReloc(F, Fixup); Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue); - } - if (Fixup.isLinkerRelaxable()) { - auto FA = MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX); - Asm->getWriter().recordRelocation(F, FA, MCValue::get(nullptr), - FixedValueA); + if (NeedsRelax) { + // Some Fixups get a RELAX relocation, record it (directly) after we add + // the relocation. + MCFixup RelaxFixup = + MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX); + MCValue RelaxTarget = MCValue::get(nullptr); + uint64_t RelaxValue; + Asm->getWriter().recordRelocation(F, RelaxFixup, RelaxTarget, RelaxValue); + } } return false; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp index cbeabdddb9371..717fba68b48ed 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -576,8 +576,21 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, "getImmOpValue expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); MCExpr::ExprKind Kind = Expr->getKind(); - unsigned FixupKind = RISCV::fixup_riscv_invalid; + + // `RelaxCandidate` must be set to `true` in two cases: + // - The fixup's relocation gets a R_RISCV_RELAX relocation + // - The underlying instruction may be relaxed to an instruction that gets a + // `R_RISCV_RELAX` relocation. + // + // The actual emission of `R_RISCV_RELAX` will be handled in + // `RISCVAsmBackend::applyFixup`. bool RelaxCandidate = false; + auto AsmRelaxToLinkerRelaxableWithFeature = [&](unsigned Feature) -> void { + if (!STI.hasFeature(RISCV::FeatureExactAssembly) && STI.hasFeature(Feature)) + RelaxCandidate = true; + }; + + unsigned FixupKind = RISCV::fixup_riscv_invalid; if (Kind == MCExpr::Specifier) { const auto *RVExpr = cast(Expr); FixupKind = RVExpr->getSpecifier(); @@ -644,18 +657,26 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, // FIXME: Sub kind binary exprs have chance of underflow. if (MIFrm == RISCVII::InstFormatJ) { FixupKind = RISCV::fixup_riscv_jal; + AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb); } else if (MIFrm == RISCVII::InstFormatB) { FixupKind = RISCV::fixup_riscv_branch; + // This might be assembler relaxed to `b; jal` but we cannot relax + // the `jal` again in the assembler. } else if (MIFrm == RISCVII::InstFormatCJ) { FixupKind = RISCV::fixup_riscv_rvc_jump; + AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb); } else if (MIFrm == RISCVII::InstFormatCB) { FixupKind = RISCV::fixup_riscv_rvc_branch; + // This might be assembler relaxed to `b; jal` but we cannot relax + // the `jal` again in the assembler. } else if (MIFrm == RISCVII::InstFormatCI) { FixupKind = RISCV::fixup_riscv_rvc_imm; } else if (MIFrm == RISCVII::InstFormatI) { FixupKind = RISCV::fixup_riscv_12_i; } else if (MIFrm == RISCVII::InstFormatQC_EB) { FixupKind = RISCV::fixup_riscv_qc_e_branch; + // This might be assembler relaxed to `qc.e.b; jal` but we cannot + // relax the `jal` again in the assembler. } else if (MIFrm == RISCVII::InstFormatQC_EAI) { FixupKind = RISCV::fixup_riscv_qc_e_32; RelaxCandidate = true; @@ -670,9 +691,9 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!"); addFixup(Fixups, 0, Expr, FixupKind); - // If linker relaxation is enabled and supported by this relocation, set - // a bit so that if fixup is unresolved, a R_RISCV_RELAX relocation will be - // appended. + // If linker relaxation is enabled and supported by this relocation, set a bit + // so that the assembler knows the size of the instruction is not fixed/known, + // and the relocation will need a R_RISCV_RELAX relocation. if (EnableRelax && RelaxCandidate) Fixups.back().setLinkerRelaxable(); ++MCNumFixups; diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.td b/llvm/lib/Target/RISCV/RISCVCallingConv.td index cbf039edec273..d8c52cbde04c7 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.td +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.td @@ -93,3 +93,7 @@ def CSR_XLEN_F32_V_Interrupt_RVE: CalleeSavedRegs<(sub CSR_XLEN_F32_V_Interrupt, // Same as CSR_XLEN_F64_V_Interrupt, but excluding X16-X31. def CSR_XLEN_F64_V_Interrupt_RVE: CalleeSavedRegs<(sub CSR_XLEN_F64_V_Interrupt, (sequence "X%u", 16, 31))>; + +def CSR_RT_MostRegs : CalleeSavedRegs<(sub CSR_Interrupt, X6, X7, X28)>; +def CSR_RT_MostRegs_RVE : CalleeSavedRegs<(sub CSR_RT_MostRegs, + (sequence "X%u", 16, 31))>; diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index a796c910bd449..c4f41b8d8e4d9 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -738,7 +738,8 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, MachineFunction &MF, uint64_t Offset, uint64_t RealStackSize, bool EmitCFI, bool NeedProbe, uint64_t ProbeSize, - bool DynAllocation) const { + bool DynAllocation, + MachineInstr::MIFlag Flag) const { DebugLoc DL; const RISCVRegisterInfo *RI = STI.getRegisterInfo(); const RISCVInstrInfo *TII = STI.getInstrInfo(); @@ -748,7 +749,7 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, // Simply allocate the stack if it's not big enough to require a probe. if (!NeedProbe || Offset <= ProbeSize) { RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(-Offset), - MachineInstr::FrameSetup, getStackAlign()); + Flag, getStackAlign()); if (EmitCFI) CFIBuilder.buildDefCFAOffset(RealStackSize); @@ -759,7 +760,7 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, .addReg(RISCV::X0) .addReg(SPReg) .addImm(0) - .setMIFlags(MachineInstr::FrameSetup); + .setMIFlags(Flag); } return; @@ -767,30 +768,30 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, // Unroll the probe loop depending on the number of iterations. if (Offset < ProbeSize * 5) { + uint64_t CFAAdjust = RealStackSize - Offset; + uint64_t CurrentOffset = 0; while (CurrentOffset + ProbeSize <= Offset) { RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, - StackOffset::getFixed(-ProbeSize), MachineInstr::FrameSetup, - getStackAlign()); + StackOffset::getFixed(-ProbeSize), Flag, getStackAlign()); // s[d|w] zero, 0(sp) BuildMI(MBB, MBBI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW)) .addReg(RISCV::X0) .addReg(SPReg) .addImm(0) - .setMIFlags(MachineInstr::FrameSetup); + .setMIFlags(Flag); CurrentOffset += ProbeSize; if (EmitCFI) - CFIBuilder.buildDefCFAOffset(CurrentOffset); + CFIBuilder.buildDefCFAOffset(CurrentOffset + CFAAdjust); } uint64_t Residual = Offset - CurrentOffset; if (Residual) { RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, - StackOffset::getFixed(-Residual), MachineInstr::FrameSetup, - getStackAlign()); + StackOffset::getFixed(-Residual), Flag, getStackAlign()); if (EmitCFI) - CFIBuilder.buildDefCFAOffset(Offset); + CFIBuilder.buildDefCFAOffset(RealStackSize); if (DynAllocation) { // s[d|w] zero, 0(sp) @@ -798,7 +799,7 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, .addReg(RISCV::X0) .addReg(SPReg) .addImm(0) - .setMIFlags(MachineInstr::FrameSetup); + .setMIFlags(Flag); } } @@ -812,8 +813,7 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, Register TargetReg = RISCV::X6; // SUB TargetReg, SP, RoundedSize RI->adjustReg(MBB, MBBI, DL, TargetReg, SPReg, - StackOffset::getFixed(-RoundedSize), MachineInstr::FrameSetup, - getStackAlign()); + StackOffset::getFixed(-RoundedSize), Flag, getStackAlign()); if (EmitCFI) { // Set the CFA register to TargetReg. @@ -830,14 +830,14 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB, if (Residual) { RI->adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackOffset::getFixed(-Residual), - MachineInstr::FrameSetup, getStackAlign()); + Flag, getStackAlign()); if (DynAllocation) { // s[d|w] zero, 0(sp) BuildMI(MBB, MBBI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW)) .addReg(RISCV::X0) .addReg(SPReg) .addImm(0) - .setMIFlags(MachineInstr::FrameSetup); + .setMIFlags(Flag); } } @@ -1034,7 +1034,8 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, MF.getInfo()->hasDynamicAllocation(); if (StackSize != 0) allocateStack(MBB, MBBI, MF, StackSize, RealStackSize, /*EmitCFI=*/true, - NeedProbe, ProbeSize, DynAllocation); + NeedProbe, ProbeSize, DynAllocation, + MachineInstr::FrameSetup); // Save SiFive CLIC CSRs into Stack emitSiFiveCLICPreemptibleSaves(MF, MBB, MBBI, DL); @@ -1082,7 +1083,7 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, allocateStack(MBB, MBBI, MF, SecondSPAdjustAmount, getStackSizeWithRVVPadding(MF), !hasFP(MF), NeedProbe, - ProbeSize, DynAllocation); + ProbeSize, DynAllocation, MachineInstr::FrameSetup); } if (RVVStackSize) { @@ -1814,7 +1815,8 @@ MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr( bool DynAllocation = MF.getInfo()->hasDynamicAllocation(); allocateStack(MBB, MI, MF, -Amount, -Amount, !hasFP(MF), - /*NeedProbe=*/true, ProbeSize, DynAllocation); + /*NeedProbe=*/true, ProbeSize, DynAllocation, + MachineInstr::NoFlags); } else { const RISCVRegisterInfo &RI = *STI.getRegisterInfo(); RI.adjustReg(MBB, MI, DL, SPReg, SPReg, StackOffset::getFixed(Amount), diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h index d013755ce58a0..6af63a4885f35 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h @@ -81,7 +81,8 @@ class RISCVFrameLowering : public TargetFrameLowering { void allocateStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineFunction &MF, uint64_t Offset, uint64_t RealStackSize, bool EmitCFI, bool NeedProbe, - uint64_t ProbeSize, bool DynAllocation) const; + uint64_t ProbeSize, bool DynAllocation, + MachineInstr::MIFlag Flag) const; protected: const RISCVSubtarget &STI; diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 666c76b21e631..186191abe12a2 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -689,10 +689,16 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) { if (!isShiftedMask_32(C1) || isInt<12>(C1)) return false; + // INSBI will clobber the input register in N0. Bail out if we need a copy to + // preserve this value. + SDValue N0 = Node->getOperand(0); + if (!N0.hasOneUse()) + return false; + // If C1 is a shifted mask (but can't be formed as an ORI), // use a bitfield insert of -1. // Transform (or x, C1) - // -> (qc.insbi x, width, shift) + // -> (qc.insbi x, -1, width, shift) const unsigned Leading = llvm::countl_zero((uint32_t)C1); const unsigned Trailing = llvm::countr_zero((uint32_t)C1); const unsigned Width = 32 - Leading - Trailing; @@ -705,7 +711,7 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInMask(SDNode *Node) { SDLoc DL(Node); MVT VT = Node->getSimpleValueType(0); - SDValue Ops[] = {CurDAG->getSignedTargetConstant(-1, DL, VT), + SDValue Ops[] = {N0, CurDAG->getSignedTargetConstant(-1, DL, VT), CurDAG->getTargetConstant(Width, DL, VT), CurDAG->getTargetConstant(Trailing, DL, VT)}; SDNode *BitIns = CurDAG->getMachineNode(RISCV::QC_INSBI, DL, VT, Ops); @@ -2936,8 +2942,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, /// Similar to SelectAddrRegImm, except that the offset is restricted to uimm9. bool RISCVDAGToDAGISel::SelectAddrRegImm9(SDValue Addr, SDValue &Base, SDValue &Offset) { - if (SelectAddrFrameIndex(Addr, Base, Offset)) - return true; + // FIXME: Support FrameIndex. Need to teach eliminateFrameIndex that only + // a 9-bit immediate can be folded. SDLoc DL(Addr); MVT VT = Addr.getSimpleValueType(); @@ -2947,8 +2953,8 @@ bool RISCVDAGToDAGISel::SelectAddrRegImm9(SDValue Addr, SDValue &Base, if (isUInt<9>(CVal)) { Base = Addr.getOperand(0); - if (auto *FIN = dyn_cast(Base)) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), VT); + // FIXME: Support FrameIndex. Need to teach eliminateFrameIndex that only + // a 9-bit immediate can be folded. Offset = CurDAG->getSignedTargetConstant(CVal, DL, VT); return true; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 9cbc364afc214..567ef2ff19f06 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16013,7 +16013,7 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG, uint64_t MulAmt = CNode->getZExtValue(); // Don't do this if the Xqciac extension is enabled and the MulAmt in simm12. - if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt)) + if (Subtarget.hasVendorXqciac() && isInt<12>(CNode->getSExtValue())) return SDValue(); const bool HasShlAdd = Subtarget.hasStdExtZba() || @@ -16936,18 +16936,9 @@ struct NodeExtensionHelper { case RISCVISD::VWSUBU_W_VL: case RISCVISD::VFWADD_W_VL: case RISCVISD::VFWSUB_W_VL: - if (OperandIdx == 1) { - SupportsZExt = - Opc == RISCVISD::VWADDU_W_VL || Opc == RISCVISD::VWSUBU_W_VL; - SupportsSExt = - Opc == RISCVISD::VWADD_W_VL || Opc == RISCVISD::VWSUB_W_VL; - SupportsFPExt = - Opc == RISCVISD::VFWADD_W_VL || Opc == RISCVISD::VFWSUB_W_VL; - // There's no existing extension here, so we don't have to worry about - // making sure it gets removed. - EnforceOneUse = false; + // Operand 1 can't be changed. + if (OperandIdx == 1) break; - } [[fallthrough]]; default: fillUpExtensionSupport(Root, DAG, Subtarget); @@ -16985,20 +16976,20 @@ struct NodeExtensionHelper { case RISCVISD::ADD_VL: case RISCVISD::MUL_VL: case RISCVISD::OR_VL: - case RISCVISD::VWADD_W_VL: - case RISCVISD::VWADDU_W_VL: case RISCVISD::FADD_VL: case RISCVISD::FMUL_VL: - case RISCVISD::VFWADD_W_VL: case RISCVISD::VFMADD_VL: case RISCVISD::VFNMSUB_VL: case RISCVISD::VFNMADD_VL: case RISCVISD::VFMSUB_VL: return true; + case RISCVISD::VWADD_W_VL: + case RISCVISD::VWADDU_W_VL: case ISD::SUB: case RISCVISD::SUB_VL: case RISCVISD::VWSUB_W_VL: case RISCVISD::VWSUBU_W_VL: + case RISCVISD::VFWADD_W_VL: case RISCVISD::FSUB_VL: case RISCVISD::VFWSUB_W_VL: case ISD::SHL: @@ -17117,6 +17108,30 @@ canFoldToVWWithSameExtension(SDNode *Root, const NodeExtensionHelper &LHS, Subtarget); } +/// Check if \p Root follows a pattern Root(zext(LHS), zext(RHS)) +/// +/// \returns std::nullopt if the pattern doesn't match or a CombineResult that +/// can be used to apply the pattern. +static std::optional +canFoldToVWWithSameExtZEXT(SDNode *Root, const NodeExtensionHelper &LHS, + const NodeExtensionHelper &RHS, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG, + Subtarget); +} + +/// Check if \p Root follows a pattern Root(bf16ext(LHS), bf16ext(RHS)) +/// +/// \returns std::nullopt if the pattern doesn't match or a CombineResult that +/// can be used to apply the pattern. +static std::optional +canFoldToVWWithSameExtBF16(SDNode *Root, const NodeExtensionHelper &LHS, + const NodeExtensionHelper &RHS, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::BF16Ext, DAG, + Subtarget); +} + /// Check if \p Root follows a pattern Root(LHS, ext(RHS)) /// /// \returns std::nullopt if the pattern doesn't match or a CombineResult that @@ -17145,7 +17160,7 @@ canFoldToVW_W(SDNode *Root, const NodeExtensionHelper &LHS, return std::nullopt; } -/// Check if \p Root follows a pattern Root(sext(LHS), sext(RHS)) +/// Check if \p Root follows a pattern Root(sext(LHS), RHS) /// /// \returns std::nullopt if the pattern doesn't match or a CombineResult that /// can be used to apply the pattern. @@ -17153,11 +17168,14 @@ static std::optional canFoldToVWWithSEXT(SDNode *Root, const NodeExtensionHelper &LHS, const NodeExtensionHelper &RHS, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { - return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::SExt, DAG, - Subtarget); + if (LHS.SupportsSExt) + return CombineResult(NodeExtensionHelper::getSExtOpcode(Root->getOpcode()), + Root, LHS, /*LHSExt=*/{ExtKind::SExt}, RHS, + /*RHSExt=*/std::nullopt); + return std::nullopt; } -/// Check if \p Root follows a pattern Root(zext(LHS), zext(RHS)) +/// Check if \p Root follows a pattern Root(zext(LHS), RHS) /// /// \returns std::nullopt if the pattern doesn't match or a CombineResult that /// can be used to apply the pattern. @@ -17165,11 +17183,14 @@ static std::optional canFoldToVWWithZEXT(SDNode *Root, const NodeExtensionHelper &LHS, const NodeExtensionHelper &RHS, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { - return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::ZExt, DAG, - Subtarget); + if (LHS.SupportsZExt) + return CombineResult(NodeExtensionHelper::getZExtOpcode(Root->getOpcode()), + Root, LHS, /*LHSExt=*/{ExtKind::ZExt}, RHS, + /*RHSExt=*/std::nullopt); + return std::nullopt; } -/// Check if \p Root follows a pattern Root(fpext(LHS), fpext(RHS)) +/// Check if \p Root follows a pattern Root(fpext(LHS), RHS) /// /// \returns std::nullopt if the pattern doesn't match or a CombineResult that /// can be used to apply the pattern. @@ -17177,20 +17198,11 @@ static std::optional canFoldToVWWithFPEXT(SDNode *Root, const NodeExtensionHelper &LHS, const NodeExtensionHelper &RHS, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { - return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::FPExt, DAG, - Subtarget); -} - -/// Check if \p Root follows a pattern Root(bf16ext(LHS), bf16ext(RHS)) -/// -/// \returns std::nullopt if the pattern doesn't match or a CombineResult that -/// can be used to apply the pattern. -static std::optional -canFoldToVWWithBF16EXT(SDNode *Root, const NodeExtensionHelper &LHS, - const NodeExtensionHelper &RHS, SelectionDAG &DAG, - const RISCVSubtarget &Subtarget) { - return canFoldToVWWithSameExtensionImpl(Root, LHS, RHS, ExtKind::BF16Ext, DAG, - Subtarget); + if (LHS.SupportsFPExt) + return CombineResult(NodeExtensionHelper::getFPExtOpcode(Root->getOpcode()), + Root, LHS, /*LHSExt=*/{ExtKind::FPExt}, RHS, + /*RHSExt=*/std::nullopt); + return std::nullopt; } /// Check if \p Root follows a pattern Root(sext(LHS), zext(RHS)) @@ -17233,7 +17245,7 @@ NodeExtensionHelper::getSupportedFoldings(const SDNode *Root) { case RISCVISD::VFNMSUB_VL: Strategies.push_back(canFoldToVWWithSameExtension); if (Root->getOpcode() == RISCVISD::VFMADD_VL) - Strategies.push_back(canFoldToVWWithBF16EXT); + Strategies.push_back(canFoldToVWWithSameExtBF16); break; case ISD::MUL: case RISCVISD::MUL_VL: @@ -17245,7 +17257,7 @@ NodeExtensionHelper::getSupportedFoldings(const SDNode *Root) { case ISD::SHL: case RISCVISD::SHL_VL: // shl -> vwsll - Strategies.push_back(canFoldToVWWithZEXT); + Strategies.push_back(canFoldToVWWithSameExtZEXT); break; case RISCVISD::VWADD_W_VL: case RISCVISD::VWSUB_W_VL: @@ -22224,6 +22236,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments( case CallingConv::C: case CallingConv::Fast: case CallingConv::SPIR_KERNEL: + case CallingConv::PreserveMost: case CallingConv::GRAAL: case CallingConv::RISCV_VectorCall: #define CC_VLS_CASE(ABI_VLEN) case CallingConv::RISCV_VLSCall_##ABI_VLEN: diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td index 26bb1e8d17857..f39130090defd 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td @@ -845,10 +845,11 @@ let Predicates = [HasVendorXqcibi, IsRV32] in { let Predicates = [HasVendorXqcibm, IsRV32] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { def QC_INSBRI : QCIRVInstRI<0b1, simm11, "qc.insbri">; - def QC_INSBI : RVInstIBase<0b001, OPC_CUSTOM_0, (outs GPRNoX0:$rd), - (ins simm5:$imm5, uimm5_plus1:$width, + def QC_INSBI : RVInstIBase<0b001, OPC_CUSTOM_0, (outs GPRNoX0:$rd_wb), + (ins GPRNoX0:$rd, simm5:$imm5, uimm5_plus1:$width, uimm5:$shamt), "qc.insbi", "$rd, $imm5, $width, $shamt"> { + let Constraints = "$rd = $rd_wb"; bits<5> imm5; bits<5> shamt; bits<5> width; @@ -1376,9 +1377,9 @@ let Predicates = [HasVendorXqciac, IsRV32] in { def : Pat<(i32 (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))), (QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>; def : Pat<(i32 (add_like_non_imm12 (shl GPRNoX0:$rs1, uimm5gt3:$imm), GPRNoX0:$rs2)), - (QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>; + (QC_SHLADD GPRNoX0:$rs1, GPRNoX0:$rs2, uimm5gt3:$imm)>; def : Pat<(i32 (riscv_shl_add GPRNoX0:$rs1, uimm5gt3:$imm, GPRNoX0:$rs2)), - (QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>; + (QC_SHLADD GPRNoX0:$rs1, GPRNoX0:$rs2, uimm5gt3:$imm)>; } // Predicates = [HasVendorXqciac, IsRV32] /// Simple arithmetic operations diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td index 4147c97a7a23a..92bc3ee8bdacc 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td @@ -1130,13 +1130,13 @@ let Predicates = [HasStdExtZvkned] in { let Predicates = [HasStdExtZvknha] in { defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ch", "PseudoVSHA2CH", I32IntegerVectors>; - defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CH", I32IntegerVectors>; + defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CL", I32IntegerVectors>; defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ms", "PseudoVSHA2MS", I32IntegerVectors, isSEWAware=true>; } // Predicates = [HasStdExtZvknha] let Predicates = [HasStdExtZvknhb] in { defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ch", "PseudoVSHA2CH", I32I64IntegerVectors>; - defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CH", I32I64IntegerVectors>; + defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2cl", "PseudoVSHA2CL", I32I64IntegerVectors>; defm : VPatBinaryV_VV_NoMask<"int_riscv_vsha2ms", "PseudoVSHA2MS", I32I64IntegerVectors, isSEWAware=true>; } // Predicates = [HasStdExtZvknhb] diff --git a/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp b/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp index 7a2541a652b58..0d37db0138e47 100644 --- a/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp +++ b/llvm/lib/Target/RISCV/RISCVMoveMerger.cpp @@ -137,6 +137,11 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I, NextI = next_nodbg(NextI, E); DebugLoc DL = I->getDebugLoc(); + // Make a copy so we can update the kill flag in the MoveFromAToS case. The + // copied operand needs to be scoped outside the if since we make a pointer + // to it. + MachineOperand PairedSource = *PairedRegs.Source; + // The order of S-reg depends on which instruction holds A0, instead of // the order of register pair. // e,g. @@ -147,8 +152,15 @@ RISCVMoveMerge::mergePairedInsns(MachineBasicBlock::iterator I, // mv a1, s1 => cm.mva01s s2,s1 bool StartWithX10 = ARegInFirstPair == RISCV::X10; if (isMoveFromAToS(Opcode)) { - Sreg1 = StartWithX10 ? FirstPair.Source : PairedRegs.Source; - Sreg2 = StartWithX10 ? PairedRegs.Source : FirstPair.Source; + // We are moving one of the copies earlier so its kill flag may become + // invalid. Clear the copied kill flag if there are any reads of the + // register between the new location and the old location. + for (auto It = std::next(I); It != Paired && PairedSource.isKill(); ++It) + if (It->readsRegister(PairedSource.getReg(), TRI)) + PairedSource.setIsKill(false); + + Sreg1 = StartWithX10 ? FirstPair.Source : &PairedSource; + Sreg2 = StartWithX10 ? &PairedSource : FirstPair.Source; } else { Sreg1 = StartWithX10 ? FirstPair.Destination : PairedRegs.Destination; Sreg2 = StartWithX10 ? PairedRegs.Destination : FirstPair.Destination; diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 540412366026b..214536d7f3a74 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -68,6 +68,9 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { auto &Subtarget = MF->getSubtarget(); if (MF->getFunction().getCallingConv() == CallingConv::GHC) return CSR_NoRegs_SaveList; + if (MF->getFunction().getCallingConv() == CallingConv::PreserveMost) + return Subtarget.hasStdExtE() ? CSR_RT_MostRegs_RVE_SaveList + : CSR_RT_MostRegs_SaveList; if (MF->getFunction().hasFnAttribute("interrupt")) { if (Subtarget.hasVInstructions()) { if (Subtarget.hasStdExtD()) @@ -811,7 +814,13 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF, if (CC == CallingConv::GHC) return CSR_NoRegs_RegMask; - switch (Subtarget.getTargetABI()) { + RISCVABI::ABI ABI = Subtarget.getTargetABI(); + if (CC == CallingConv::PreserveMost) { + if (ABI == RISCVABI::ABI_ILP32E || ABI == RISCVABI::ABI_LP64E) + return CSR_RT_MostRegs_RVE_RegMask; + return CSR_RT_MostRegs_RegMask; + } + switch (ABI) { default: llvm_unreachable("Unrecognized ABI"); case RISCVABI::ABI_ILP32E: diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 56ead92187b04..70cfb4b836ccc 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1567,6 +1567,7 @@ InstructionCost RISCVTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, // scalarized if the legalized Src and Dst are not equal sized. const DataLayout &DL = this->getDataLayout(); if (!SrcLT.second.isVector() || !DstLT.second.isVector() || + !SrcLT.first.isValid() || !DstLT.first.isValid() || !TypeSize::isKnownLE(DL.getTypeSizeInBits(Src), SrcLT.second.getSizeInBits()) || !TypeSize::isKnownLE(DL.getTypeSizeInBits(Dst), diff --git a/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp b/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp index 84ef53985484f..c1cc19b503deb 100644 --- a/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp +++ b/llvm/lib/Target/RISCV/RISCVVectorPeephole.cpp @@ -434,6 +434,15 @@ bool RISCVVectorPeephole::convertSameMaskVMergeToVMv(MachineInstr &MI) { if (!isKnownSameDefs(TrueMask.getReg(), MIMask.getReg())) return false; + // Masked off lanes past TrueVL will come from False, and converting to vmv + // will lose these lanes unless MIVL <= TrueVL. + // TODO: We could relax this for False == Passthru and True policy == TU + const MachineOperand &MIVL = MI.getOperand(RISCVII::getVLOpNum(MI.getDesc())); + const MachineOperand &TrueVL = + True->getOperand(RISCVII::getVLOpNum(True->getDesc())); + if (!RISCV::isVLKnownLE(MIVL, TrueVL)) + return false; + // True's passthru needs to be equivalent to False Register TruePassthruReg = True->getOperand(1).getReg(); Register FalseReg = MI.getOperand(2).getReg(); diff --git a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp index 6c19049a001cf..024030d196ee3 100644 --- a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp @@ -206,8 +206,8 @@ Filler::findDelayInstr(MachineBasicBlock &MBB, if (!done) --I; - // skip debug instruction - if (I->isDebugInstr()) + // Skip meta instructions. + if (I->isMetaInstruction()) continue; if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() || diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 9b434d87c2676..57e7ff3a52cec 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -115,7 +115,8 @@ static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, // Stack space is allocated for all arguments starting from [%fp+BIAS+128]. unsigned size = (LocVT == MVT::f128) ? 16 : 8; - Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8); + Align alignment = + (LocVT == MVT::f128 || ArgFlags.isSplit()) ? Align(16) : Align(8); unsigned Offset = State.AllocateStack(size, alignment); unsigned Reg = 0; @@ -1799,12 +1800,14 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FCOS , MVT::f64, Expand); setOperationAction(ISD::FSINCOS, MVT::f64, Expand); setOperationAction(ISD::FREM , MVT::f64, Expand); - setOperationAction(ISD::FMA , MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f64, + Subtarget->isUA2007() ? Legal : Expand); setOperationAction(ISD::FSIN , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FSINCOS, MVT::f32, Expand); setOperationAction(ISD::FREM , MVT::f32, Expand); - setOperationAction(ISD::FMA, MVT::f32, Expand); + setOperationAction(ISD::FMA, MVT::f32, + Subtarget->isUA2007() ? Legal : Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); @@ -2201,7 +2204,7 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, SDValue Chain = DAG.getEntryNode(); SDValue InGlue; - Chain = DAG.getCALLSEQ_START(Chain, 1, 0, DL); + Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL); Chain = DAG.getCopyToReg(Chain, DL, SP::O0, Argument, InGlue); InGlue = Chain.getValue(1); SDValue Callee = DAG.getTargetExternalSymbol("__tls_get_addr", PtrVT); @@ -2219,7 +2222,7 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op, InGlue}; Chain = DAG.getNode(SPISD::TLS_CALL, DL, NodeTys, Ops); InGlue = Chain.getValue(1); - Chain = DAG.getCALLSEQ_END(Chain, 1, 0, InGlue, DL); + Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InGlue, DL); InGlue = Chain.getValue(1); SDValue Ret = DAG.getCopyFromReg(Chain, DL, SP::O0, PtrVT, InGlue); @@ -3550,6 +3553,11 @@ bool SparcTargetLowering::isCheapToSpeculateCttz(Type *Ty) const { return isCheapToSpeculateCtlz(Ty); } +bool SparcTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, + EVT VT) const { + return Subtarget->isUA2007() && !Subtarget->useSoftFloat(); +} + // Override to disable global variable loading on Linux. void SparcTargetLowering::insertSSPDeclarations(Module &M) const { if (!Subtarget->isTargetLinux()) diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 0d220f8c3d32e..4017beb88ff31 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -177,6 +177,11 @@ namespace llvm { bool isCheapToSpeculateCttz(Type *Ty) const override; + bool enableAggressiveFMAFusion(EVT VT) const override { return true; }; + + bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, + EVT VT) const override; + bool shouldInsertFencesForAtomic(const Instruction *I) const override { // FIXME: We insert fences for each atomics and generate // sub-optimal code for PSO/TSO. (Approximately nobody uses any diff --git a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td index 3a30e552e6db1..ffd4423137e3f 100644 --- a/llvm/lib/Target/Sparc/SparcInstrUAOSA.td +++ b/llvm/lib/Target/Sparc/SparcInstrUAOSA.td @@ -66,3 +66,15 @@ defm CXBCOND : F2_56<"cxb", 1>; def FPMADDX : FourOp<"fpmaddx", 0b110111, 0b0000, DFPRegs>; def FPMADDXHI : FourOp<"fpmaddxhi", 0b110111, 0b0100, DFPRegs>; } // Predicates = [HasOSA2011] + +// UA2007 instruction patterns. +let Predicates = [HasUA2007] in { +def : Pat<(f32 (any_fma f32:$rs1, f32:$rs2, f32:$add)), (FMADDS $rs1, $rs2, $add)>; +def : Pat<(f64 (any_fma f64:$rs1, f64:$rs2, f64:$add)), (FMADDD $rs1, $rs2, $add)>; +def : Pat<(f32 (any_fma f32:$rs1, f32:$rs2, (fneg f32:$sub))), (FMSUBS $rs1, $rs2, $sub)>; +def : Pat<(f64 (any_fma f64:$rs1, f64:$rs2, (fneg f64:$sub))), (FMSUBD $rs1, $rs2, $sub)>; +def : Pat<(f32 (fneg (any_fma f32:$rs1, f32:$rs2, f32:$add))), (FNMADDS $rs1, $rs2, $add)>; +def : Pat<(f64 (fneg (any_fma f64:$rs1, f64:$rs2, f64:$add))), (FNMADDD $rs1, $rs2, $add)>; +def : Pat<(f32 (fneg (any_fma f32:$rs1, f32:$rs2, (fneg f32:$sub)))), (FNMSUBS $rs1, $rs2, $sub)>; +def : Pat<(f64 (fneg (any_fma f64:$rs1, f64:$rs2, (fneg f64:$sub)))), (FNMSUBD $rs1, $rs2, $sub)>; +} // Predicates = [HasUA2007] diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp index f32c9bd2bdea1..2611c291abaa6 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -436,20 +436,6 @@ bool SystemZTTIImpl::isLSRCostLess( C2.ScaleCost, C2.SetupCost); } -bool SystemZTTIImpl::areInlineCompatible(const Function *Caller, - const Function *Callee) const { - const TargetMachine &TM = getTLI()->getTargetMachine(); - - const FeatureBitset &CallerBits = - TM.getSubtargetImpl(*Caller)->getFeatureBits(); - const FeatureBitset &CalleeBits = - TM.getSubtargetImpl(*Callee)->getFeatureBits(); - - // Support only equal feature bitsets. Restriction should be relaxed in the - // future to allow inlining when callee's bits are subset of the caller's. - return CallerBits == CalleeBits; -} - unsigned SystemZTTIImpl::getNumberOfRegisters(unsigned ClassID) const { bool Vector = (ClassID == 1); if (!Vector) diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h index dc5736e8af009..fc681dec1859a 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.h @@ -65,9 +65,6 @@ class SystemZTTIImpl final : public BasicTTIImplBase { bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) const override; - bool areInlineCompatible(const Function *Caller, - const Function *Callee) const override; - /// @} /// \name Vector TTI Implementations diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp index 2662241ef8499..5c3127e2d3dc6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -216,6 +216,18 @@ static MachineInstr *findStartOfTree(MachineOperand &MO, return Def; } +// FAKE_USEs are no-ops, so remove them here so that the values used by them +// will be correctly dropped later. +static void removeFakeUses(MachineFunction &MF) { + SmallVector ToDelete; + for (auto &MBB : MF) + for (auto &MI : MBB) + if (MI.isFakeUse()) + ToDelete.push_back(&MI); + for (auto *MI : ToDelete) + MI->eraseFromParent(); +} + bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "********** Make Locals Explicit **********\n" "********** Function: " @@ -226,6 +238,8 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { WebAssemblyFunctionInfo &MFI = *MF.getInfo(); const auto *TII = MF.getSubtarget().getInstrInfo(); + removeFakeUses(MF); + // Map non-stackified virtual registers to their local ids. DenseMap Reg2Local; @@ -256,9 +270,17 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) { // Precompute the set of registers that are unused, so that we can insert // drops to their defs. + // And unstackify any stackified registers that don't have any uses, so that + // they can be dropped later. This can happen when transformations after + // RegStackify remove instructions using stackified registers. BitVector UseEmpty(MRI.getNumVirtRegs()); - for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) - UseEmpty[I] = MRI.use_empty(Register::index2VirtReg(I)); + for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) { + Register Reg = Register::index2VirtReg(I); + if (MRI.use_empty(Reg)) { + UseEmpty[I] = true; + MFI.unstackifyVReg(Reg); + } + } // Visit each instruction in the function. for (MachineBasicBlock &MBB : MF) { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp index bc91c6424b63e..fd13ef9a1921d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -866,6 +866,10 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) { if (Insert->isDebugValue()) continue; + // Ignore FAKE_USEs, which are no-ops and will be deleted later. + if (Insert->isFakeUse()) + continue; + // Iterate through the inputs in reverse order, since we'll be pulling // operands off the stack in LIFO order. CommutingState Commuting; diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index b642c1cfe383b..8213e512f45e1 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1042,8 +1042,8 @@ class X86AsmParser : public MCTargetAsmParser { } PrevState = CurrState; } - void onRParen() { - PrevState = State; + bool onRParen(StringRef &ErrMsg) { + IntelExprState CurrState = State; switch (State) { default: State = IES_ERROR; @@ -1054,9 +1054,27 @@ class X86AsmParser : public MCTargetAsmParser { case IES_RBRAC: case IES_RPAREN: State = IES_RPAREN; + // In the case of a multiply, onRegister has already set IndexReg + // directly, with appropriate scale. + // Otherwise if we just saw a register it has only been stored in + // TmpReg, so we need to store it into the state machine. + if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) { + // If we already have a BaseReg, then assume this is the IndexReg with + // no explicit scale. + if (!BaseReg) { + BaseReg = TmpReg; + } else { + if (IndexReg) + return regsUseUpError(ErrMsg); + IndexReg = TmpReg; + Scale = 0; + } + } IC.pushOperator(IC_RPAREN); break; } + PrevState = CurrState; + return false; } bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID, const InlineAsmIdentifierInfo &IDInfo, @@ -2172,7 +2190,11 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { } break; case AsmToken::LParen: SM.onLParen(); break; - case AsmToken::RParen: SM.onRParen(); break; + case AsmToken::RParen: + if (SM.onRParen(ErrMsg)) { + return Error(Tok.getLoc(), ErrMsg); + } + break; } if (SM.hadError()) return Error(Tok.getLoc(), "unknown token in expression"); diff --git a/llvm/lib/Target/X86/X86CallingConv.cpp b/llvm/lib/Target/X86/X86CallingConv.cpp index 0b4c63f7a81f7..5d5a705893242 100644 --- a/llvm/lib/Target/X86/X86CallingConv.cpp +++ b/llvm/lib/Target/X86/X86CallingConv.cpp @@ -374,5 +374,36 @@ static bool CC_X86_64_I128(unsigned &ValNo, MVT &ValVT, MVT &LocVT, return true; } +/// Special handling for i128 and fp128: on x86-32, i128 and fp128 get legalized +/// as four i32s, but fp128 must be passed on the stack with 16-byte alignment. +/// Technically only fp128 has a specified ABI, but it makes sense to handle +/// i128 the same until we hear differently. +static bool CC_X86_32_I128_FP128(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + assert(ValVT == MVT::i32 && "Should have i32 parts"); + SmallVectorImpl &PendingMembers = State.getPendingLocs(); + PendingMembers.push_back( + CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); + + if (!ArgFlags.isInConsecutiveRegsLast()) + return true; + + assert(PendingMembers.size() == 4 && "Should have four parts"); + + int64_t Offset = State.AllocateStack(16, Align(16)); + PendingMembers[0].convertToMem(Offset); + PendingMembers[1].convertToMem(Offset + 4); + PendingMembers[2].convertToMem(Offset + 8); + PendingMembers[3].convertToMem(Offset + 12); + + State.addLoc(PendingMembers[0]); + State.addLoc(PendingMembers[1]); + State.addLoc(PendingMembers[2]); + State.addLoc(PendingMembers[3]); + PendingMembers.clear(); + return true; +} + // Provides entry points of CC_X86 and RetCC_X86. #include "X86GenCallingConv.inc" diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td index 823e0caa02262..f020e0b55141c 100644 --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -859,6 +859,11 @@ def CC_X86_32_C : CallingConv<[ // The 'nest' parameter, if any, is passed in ECX. CCIfNest>, + // i128 and fp128 need to be passed on the stack with a higher alignment than + // their legal types. Handle this with a custom function. + CCIfType<[i32], + CCIfConsecutiveRegs>>, + // On swifttailcc pass swiftself in ECX. CCIfCC<"CallingConv::SwiftTail", CCIfSwiftSelf>>>, diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5e35d5630d667..c91bf269076ef 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4997,9 +4997,12 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, EVT VT = Op.getValueType(); unsigned SizeInBits = VT.getSizeInBits(); - assert((SizeInBits % EltSizeInBits) == 0 && "Can't split constant!"); unsigned NumElts = SizeInBits / EltSizeInBits; + // Can't split constant. + if ((SizeInBits % EltSizeInBits) != 0) + return false; + // Bitcast a source array of element bits to the target size. auto CastBitData = [&](APInt &UndefSrcElts, ArrayRef SrcEltBits) { unsigned NumSrcElts = UndefSrcElts.getBitWidth(); @@ -15400,18 +15403,18 @@ static SDValue lowerShuffleAsLanePermuteAndPermute( return SDValue(); } - // Avoid returning the same shuffle operation. For example, - // t7: v16i16 = vector_shuffle<8,9,10,11,4,5,6,7,0,1,2,3,12,13,14,15> t5, - // undef:v16i16 - if (CrossLaneMask == Mask || InLaneMask == Mask) - return SDValue(); - // Simplify CrossLaneMask based on the actual demanded elements. if (V1.hasOneUse()) for (int i = 0; i != NumElts; ++i) if (!DemandedCrossLane[i]) CrossLaneMask[i] = SM_SentinelUndef; + // Avoid returning the same shuffle operation. For example, + // t7: v16i16 = vector_shuffle<8,9,10,11,4,5,6,7,0,1,2,3,12,13,14,15> t5, + // undef:v16i16 + if (CrossLaneMask == Mask || InLaneMask == Mask) + return SDValue(); + SDValue CrossLane = DAG.getVectorShuffle(VT, DL, V1, V2, CrossLaneMask); return DAG.getVectorShuffle(VT, DL, CrossLane, DAG.getUNDEF(VT), InLaneMask); @@ -26233,10 +26236,9 @@ static SDValue getScalarMaskingNode(SDValue Op, SDValue Mask, SDValue PreservedSrc, const X86Subtarget &Subtarget, SelectionDAG &DAG) { - - if (auto *MaskConst = dyn_cast(Mask)) - if (MaskConst->getZExtValue() & 0x1) - return Op; + auto *MaskConst = dyn_cast(Mask); + if (MaskConst && (MaskConst->getZExtValue() & 0x1)) + return Op; MVT VT = Op.getSimpleValueType(); SDLoc dl(Op); @@ -26252,6 +26254,17 @@ static SDValue getScalarMaskingNode(SDValue Op, SDValue Mask, if (PreservedSrc.isUndef()) PreservedSrc = getZeroVector(VT, Subtarget, DAG, dl); + + if (MaskConst) { + assert((MaskConst->getZExtValue() & 0x1) == 0 && "Expected false mask"); + // Discard op and blend passthrough with scalar op src/dst. + SmallVector ShuffleMask(VT.getVectorNumElements()); + std::iota(ShuffleMask.begin(), ShuffleMask.end(), 0); + ShuffleMask[0] = VT.getVectorNumElements(); + return DAG.getVectorShuffle(VT, dl, Op.getOperand(0), PreservedSrc, + ShuffleMask); + } + return DAG.getNode(X86ISD::SELECTS, dl, VT, IMask, Op, PreservedSrc); } @@ -44175,8 +44188,12 @@ bool X86TargetLowering::SimplifyDemandedVectorEltsForTargetNode( } // Conversions. // TODO: Add more CVT opcodes when we have test coverage. - case X86ISD::CVTTP2SI: case X86ISD::CVTTP2UI: { + if (!Subtarget.hasVLX()) + break; + [[fallthrough]]; + } + case X86ISD::CVTTP2SI: { if (Op.getOperand(0).getValueType().getVectorElementType() == MVT::f16 && !Subtarget.hasVLX()) break; @@ -51758,6 +51775,8 @@ static SDValue combineAnd(SDNode *N, SelectionDAG &DAG, SDValue X, Y; EVT CondVT = VT.changeVectorElementType(MVT::i1); if (TLI.isTypeLegal(VT) && TLI.isTypeLegal(CondVT) && + (VT.is512BitVector() || Subtarget.hasVLX()) && + (VT.getScalarSizeInBits() >= 32 || Subtarget.hasBWI()) && sd_match(N, m_And(m_Value(X), m_OneUse(m_SExt(m_AllOf( m_Value(Y), m_SpecificVT(CondVT), @@ -55312,6 +55331,8 @@ static SDValue combineAndnp(SDNode *N, SelectionDAG &DAG, SDValue Src = N0.getOperand(0); EVT SrcVT = Src.getValueType(); if (Src.getOpcode() == ISD::SETCC && SrcVT.getScalarType() == MVT::i1 && + (VT.is512BitVector() || Subtarget.hasVLX()) && + (VT.getScalarSizeInBits() >= 32 || Subtarget.hasBWI()) && TLI.isTypeLegal(SrcVT) && N0.hasOneUse() && Src.hasOneUse()) return DAG.getSelect(DL, VT, DAG.getNOT(DL, Src, SrcVT), N1, getZeroVector(VT, Subtarget, DAG, DL)); @@ -56191,7 +56212,13 @@ static SDValue combineAVX512SetCCToKMOV(EVT VT, SDValue Op0, ISD::CondCode CC, SDValue Masked = BroadcastOp; if (N != 0) { - APInt Mask = APInt::getLowBitsSet(BroadcastOpVT.getSizeInBits(), Len); + unsigned BroadcastOpBitWidth = BroadcastOpVT.getSizeInBits(); + unsigned NumDefinedElts = UndefElts.countTrailingZeros(); + + if (NumDefinedElts > BroadcastOpBitWidth) + return SDValue(); + + APInt Mask = APInt::getLowBitsSet(BroadcastOpBitWidth, NumDefinedElts); SDValue ShiftedValue = DAG.getNode(ISD::SRL, DL, BroadcastOpVT, BroadcastOp, DAG.getConstant(N, DL, BroadcastOpVT)); Masked = DAG.getNode(ISD::AND, DL, BroadcastOpVT, ShiftedValue, diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp index 9ad355311527b..b4639ac2577e8 100644 --- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp +++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp @@ -237,9 +237,18 @@ EVT X86TargetLowering::getSetCCResultType(const DataLayout &DL, bool X86TargetLowering::functionArgumentNeedsConsecutiveRegisters( Type *Ty, CallingConv::ID CallConv, bool isVarArg, const DataLayout &DL) const { - // i128 split into i64 needs to be allocated to two consecutive registers, - // or spilled to the stack as a whole. - return Ty->isIntegerTy(128); + // On x86-64 i128 is split into two i64s and needs to be allocated to two + // consecutive registers, or spilled to the stack as a whole. On x86-32 i128 + // is split to four i32s and never actually passed in registers, but we use + // the consecutive register mark to match it in TableGen. + if (Ty->isIntegerTy(128)) + return true; + + // On x86-32, fp128 acts the same as i128. + if (Subtarget.is32Bit() && Ty->isFP128Ty()) + return true; + + return false; } /// Helper for getByValTypeAlignment to determine diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index abf365eedec39..9bf58dd3458cd 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -10739,39 +10739,27 @@ void X86InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB, if (!ST.hasSSE1()) return; - // PXOR is safe to use because it doesn't affect flags. - BuildMI(MBB, Iter, DL, get(X86::PXORrr), Reg) - .addReg(Reg, RegState::Undef) - .addReg(Reg, RegState::Undef); + BuildMI(MBB, Iter, DL, get(X86::V_SET0), Reg); } else if (X86::VR256RegClass.contains(Reg)) { // YMM# if (!ST.hasAVX()) return; - // VPXOR is safe to use because it doesn't affect flags. - BuildMI(MBB, Iter, DL, get(X86::VPXORrr), Reg) - .addReg(Reg, RegState::Undef) - .addReg(Reg, RegState::Undef); + BuildMI(MBB, Iter, DL, get(X86::AVX_SET0), Reg); } else if (X86::VR512RegClass.contains(Reg)) { // ZMM# if (!ST.hasAVX512()) return; - // VPXORY is safe to use because it doesn't affect flags. - BuildMI(MBB, Iter, DL, get(X86::VPXORYrr), Reg) - .addReg(Reg, RegState::Undef) - .addReg(Reg, RegState::Undef); + BuildMI(MBB, Iter, DL, get(X86::AVX512_512_SET0), Reg); } else if (X86::VK1RegClass.contains(Reg) || X86::VK2RegClass.contains(Reg) || X86::VK4RegClass.contains(Reg) || X86::VK8RegClass.contains(Reg) || X86::VK16RegClass.contains(Reg)) { if (!ST.hasVLX()) return; - // KXOR is safe to use because it doesn't affect flags. - unsigned Op = ST.hasBWI() ? X86::KXORQkk : X86::KXORWkk; - BuildMI(MBB, Iter, DL, get(Op), Reg) - .addReg(Reg, RegState::Undef) - .addReg(Reg, RegState::Undef); + unsigned Op = ST.hasBWI() ? X86::KSET0Q : X86::KSET0W; + BuildMI(MBB, Iter, DL, get(Op), Reg); } } diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index fd42fd2e010ba..f847ddb46af76 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -232,12 +232,6 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal); setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal); setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal); - - setCondCodeAction(ISD::SETOGT, MVT::f32, Expand); - setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); - setCondCodeAction(ISD::SETONE, MVT::f32, Expand); - setCondCodeAction(ISD::SETUGE, MVT::f32, Expand); - setCondCodeAction(ISD::SETUGT, MVT::f32, Expand); } else { setOperationAction(ISD::BITCAST, MVT::i32, Expand); setOperationAction(ISD::BITCAST, MVT::f32, Expand); @@ -877,6 +871,16 @@ static std::pair getFPBranchKind(ISD::CondCode Cond) { return std::make_pair(Xtensa::BF, Xtensa::OLT_S); case ISD::SETGT: return std::make_pair(Xtensa::BF, Xtensa::OLE_S); + case ISD::SETOGT: + return std::make_pair(Xtensa::BF, Xtensa::ULE_S); + case ISD::SETOGE: + return std::make_pair(Xtensa::BF, Xtensa::ULT_S); + case ISD::SETONE: + return std::make_pair(Xtensa::BF, Xtensa::UEQ_S); + case ISD::SETUGT: + return std::make_pair(Xtensa::BF, Xtensa::OLE_S); + case ISD::SETUGE: + return std::make_pair(Xtensa::BF, Xtensa::OLT_S); default: llvm_unreachable("Invalid condition!"); } diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp index 59ae057cae793..ac93f748ce65c 100644 --- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -85,6 +85,9 @@ static Intrinsic::ID NonOverloadedCoroIntrinsics[] = { Intrinsic::coro_id_async, Intrinsic::coro_id_retcon, Intrinsic::coro_id_retcon_once, + Intrinsic::coro_noop, + Intrinsic::coro_prepare_async, + Intrinsic::coro_prepare_retcon, Intrinsic::coro_promise, Intrinsic::coro_resume, Intrinsic::coro_save, diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index e276376f21583..0d631734ca968 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -350,12 +350,20 @@ void splitAndWriteThinLTOBitcode( }); } + auto MustEmitToMergedModule = [](const GlobalValue *GV) { + // The __cfi_check definition is filled in by the CrossDSOCFI pass which + // runs only in the merged module. + return GV->getName() == "__cfi_check"; + }; + ValueToValueMapTy VMap; std::unique_ptr MergedM( CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool { if (const auto *C = GV->getComdat()) if (MergedMComdats.count(C)) return true; + if (MustEmitToMergedModule(GV)) + return true; if (auto *F = dyn_cast(GV)) return EligibleVirtualFns.count(F); if (auto *GVar = @@ -372,7 +380,7 @@ void splitAndWriteThinLTOBitcode( cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true); for (Function &F : *MergedM) - if (!F.isDeclaration()) { + if (!F.isDeclaration() && !MustEmitToMergedModule(&F)) { // Reset the linkage of all functions eligible for virtual constant // propagation. The canonical definitions live in the thin LTO module so // that they can be imported. @@ -394,6 +402,8 @@ void splitAndWriteThinLTOBitcode( if (const auto *C = GV->getComdat()) if (MergedMComdats.count(C)) return false; + if (MustEmitToMergedModule(GV)) + return false; return true; }); diff --git a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp index 5ef6ffb58a7c1..667fdb746175f 100644 --- a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp @@ -90,6 +90,9 @@ PreservedAnalyses RealtimeSanitizerPass::run(Module &M, [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); }); for (Function &F : M) { + if (F.empty()) + continue; + if (F.hasFnAttribute(Attribute::SanitizeRealtime)) runSanitizeRealtime(F); diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 5b8ea1547ca2f..b74a0708b67ae 100644 --- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -1084,8 +1084,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, auto ThenTerm = SplitBlockAndInsertIfThen( IRB.CreateIsNull(Load), &*IP, false, MDBuilder(IRB.getContext()).createUnlikelyBranchWeights()); - IRBuilder<> ThenIRB(ThenTerm); + InstrumentationIRBuilder ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(ConstantInt::getTrue(Int1Ty), FlagPtr); + if (EntryLoc) + Store->setDebugLoc(EntryLoc); Load->setNoSanitizeMetadata(); Store->setNoSanitizeMetadata(); } @@ -1131,7 +1133,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, EstimatedStackSize >= Options.StackDepthCallbackMin) { if (InsertBefore) IRB.SetInsertPoint(InsertBefore); - IRB.CreateCall(SanCovStackDepthCallback)->setCannotMerge(); + auto Call = IRB.CreateCall(SanCovStackDepthCallback); + if (EntryLoc) + Call->setDebugLoc(EntryLoc); + Call->setCannotMerge(); } } else { // Check stack depth. If it's the deepest so far, record it. @@ -1144,8 +1149,10 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, auto ThenTerm = SplitBlockAndInsertIfThen( IsStackLower, &*IP, false, MDBuilder(IRB.getContext()).createUnlikelyBranchWeights()); - IRBuilder<> ThenIRB(ThenTerm); + InstrumentationIRBuilder ThenIRB(ThenTerm); auto Store = ThenIRB.CreateStore(FrameAddrInt, SanCovLowestStack); + if (EntryLoc) + Store->setDebugLoc(EntryLoc); LowestStack->setNoSanitizeMetadata(); Store->setNoSanitizeMetadata(); } diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 85dd9a1bf7161..0f63ed0166cf4 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -2079,6 +2079,7 @@ struct DSEState { AllocFnKind AllocKind = Attrs.getFnAttr(Attribute::AllocKind).getAllocKind() | AllocFnKind::Zeroed; + AllocKind &= ~AllocFnKind::Uninitialized; Attrs = Attrs.addFnAttribute(Ctx, Attribute::getWithAllocKind(Ctx, AllocKind)) .removeFnAttribute(Ctx, "alloc-variant-zeroed"); diff --git a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index 221094f170ac7..b9546c5fa236b 100644 --- a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -128,6 +128,8 @@ class ConstantTerminatorFoldingImpl { // from any other block. So this variable set to true means that loop's latch // has become unreachable from loop header. bool DeleteCurrentLoop = false; + // Whether or not we enter the loop through an indirectbr. + bool HasIndirectEntry = false; // The blocks of the original loop that will still be reachable from entry // after the constant folding. @@ -216,6 +218,19 @@ class ConstantTerminatorFoldingImpl { return; } + // We need a loop preheader to split in handleDeadExits(). If LoopSimplify + // wasn't able to form one because the loop can be entered through an + // indirectbr we cannot continue. + if (!L.getLoopPreheader()) { + assert(any_of(predecessors(L.getHeader()), + [&](BasicBlock *Pred) { + return isa(Pred->getTerminator()); + }) && + "Loop should have preheader if it is not entered indirectly"); + HasIndirectEntry = true; + return; + } + // Collect live and dead loop blocks and exits. LiveLoopBlocks.insert(L.getHeader()); for (auto I = DFS.beginRPO(), E = DFS.endRPO(); I != E; ++I) { @@ -546,6 +561,12 @@ class ConstantTerminatorFoldingImpl { return false; } + if (HasIndirectEntry) { + LLVM_DEBUG(dbgs() << "Loops which can be entered indirectly are not" + " supported!\n"); + return false; + } + // Nothing to constant-fold. if (FoldCandidates.empty()) { LLVM_DEBUG( diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 70b4552190a4e..f537b0d3fbd75 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -1258,8 +1258,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor { "Map index doesn't point back to a slice with this user."); } - // Disable SRoA for any intrinsics except for lifetime invariants and - // invariant group. + // Disable SRoA for any intrinsics except for lifetime invariants. // FIXME: What about debug intrinsics? This matches old behavior, but // doesn't make sense. void visitIntrinsicInst(IntrinsicInst &II) { @@ -1279,12 +1278,6 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor { return; } - if (II.isLaunderOrStripInvariantGroup()) { - insertUse(II, Offset, AllocSize, true); - enqueueUsers(II); - return; - } - Base::visitIntrinsicInst(II); } @@ -3618,8 +3611,7 @@ class AllocaSliceRewriter : public InstVisitor { } bool visitIntrinsicInst(IntrinsicInst &II) { - assert((II.isLifetimeStartOrEnd() || II.isLaunderOrStripInvariantGroup() || - II.isDroppable()) && + assert((II.isLifetimeStartOrEnd() || II.isDroppable()) && "Unexpected intrinsic!"); LLVM_DEBUG(dbgs() << " original: " << II << "\n"); @@ -3633,9 +3625,6 @@ class AllocaSliceRewriter : public InstVisitor { return true; } - if (II.isLaunderOrStripInvariantGroup()) - return true; - assert(II.getArgOperand(1) == OldPtr); // Lifetime intrinsics are only promotable if they cover the whole alloca. // Therefore, we drop lifetime intrinsics which don't cover the whole diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp index ddd203f3acf71..42b1fdf17f389 100644 --- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -111,15 +111,14 @@ BasicBlock * llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options, const Twine &BBName) { - assert(!isa(TI) && - "Cannot split critical edge from IndirectBrInst"); - BasicBlock *TIBB = TI->getParent(); BasicBlock *DestBB = TI->getSuccessor(SuccNum); - // Splitting the critical edge to a pad block is non-trivial. Don't do - // it in this generic function. - if (DestBB->isEHPad()) return nullptr; + // Splitting the critical edge to a pad block is non-trivial. + // And we cannot split block with IndirectBr as a terminator. + // Don't do it in this generic function. + if (DestBB->isEHPad() || isa(TI)) + return nullptr; if (Options.IgnoreUnreachableDests && isa(DestBB->getFirstNonPHIOrDbgOrLifetime())) diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 200d1fb854155..e7623aaff105d 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -938,8 +938,10 @@ constexpr Intrinsic::ID llvm::getReductionIntrinsicID(RecurKind RK) { case RecurKind::UMin: return Intrinsic::vector_reduce_umin; case RecurKind::FMax: + case RecurKind::FMaxNum: return Intrinsic::vector_reduce_fmax; case RecurKind::FMin: + case RecurKind::FMinNum: return Intrinsic::vector_reduce_fmin; case RecurKind::FMaximum: return Intrinsic::vector_reduce_fmaximum; @@ -1037,8 +1039,10 @@ Intrinsic::ID llvm::getMinMaxReductionIntrinsicOp(RecurKind RK) { case RecurKind::SMax: return Intrinsic::smax; case RecurKind::FMin: + case RecurKind::FMinNum: return Intrinsic::minnum; case RecurKind::FMax: + case RecurKind::FMaxNum: return Intrinsic::maxnum; case RecurKind::FMinimum: return Intrinsic::minimum; @@ -1096,9 +1100,9 @@ Value *llvm::createMinMaxOp(IRBuilderBase &Builder, RecurKind RK, Value *Left, Value *Right) { Type *Ty = Left->getType(); if (Ty->isIntOrIntVectorTy() || - (RK == RecurKind::FMinimum || RK == RecurKind::FMaximum || + (RK == RecurKind::FMinNum || RK == RecurKind::FMaxNum || + RK == RecurKind::FMinimum || RK == RecurKind::FMaximum || RK == RecurKind::FMinimumNum || RK == RecurKind::FMaximumNum)) { - // TODO: Add float minnum/maxnum support when FMF nnan is set. Intrinsic::ID Id = getMinMaxReductionIntrinsicOp(RK); return Builder.CreateIntrinsic(Ty, Id, {Left, Right}, nullptr, "rdx.minmax"); @@ -1308,6 +1312,8 @@ Value *llvm::createSimpleReduction(IRBuilderBase &Builder, Value *Src, case RecurKind::UMin: case RecurKind::FMax: case RecurKind::FMin: + case RecurKind::FMinNum: + case RecurKind::FMaxNum: case RecurKind::FMinimum: case RecurKind::FMaximum: case RecurKind::FMinimumNum: diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index 24fe08d6c3e4e..bf457194bfd8e 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -2133,8 +2133,15 @@ Value *SCEVExpander::generateOverflowCheck(const SCEVAddRecExpr *AR, // negative. If Step is known to be positive or negative, only create // either 1. or 2. auto ComputeEndCheck = [&]() -> Value * { - // Checking isZero() && SE.isKnownPositive(Step)) + // Checking isZero() && SE.isKnownPositive(Step) && + DstBits < SrcBits && + ExitCount == SE.getZeroExtendExpr(SE.getTruncateExpr(ExitCount, ARTy), + ExitCount->getType()) && + SE.willNotOverflow(Instruction::Mul, Signed, Step, + SE.getTruncateExpr(ExitCount, ARTy))) return ConstantInt::getFalse(Loc->getContext()); // Get the backedge taken count and truncate or extended to the AR type. diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index 11853859484e3..f57ce0c3ccb4d 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -230,7 +230,6 @@ class VPBuilder { /// Create a new ICmp VPInstruction with predicate \p Pred and operands \p A /// and \p B. - /// TODO: add createFCmp when needed. VPInstruction *createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "") { @@ -240,6 +239,17 @@ class VPBuilder { new VPInstruction(Instruction::ICmp, {A, B}, Pred, DL, Name)); } + /// Create a new FCmp VPInstruction with predicate \p Pred and operands \p A + /// and \p B. + VPInstruction *createFCmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, + DebugLoc DL = DebugLoc::getUnknown(), + const Twine &Name = "") { + assert(Pred >= CmpInst::FIRST_FCMP_PREDICATE && + Pred <= CmpInst::LAST_FCMP_PREDICATE && "invalid predicate"); + return tryInsertInstruction( + new VPInstruction(Instruction::FCmp, {A, B}, Pred, DL, Name)); + } + VPInstruction *createPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "") { diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 06db89a89bc38..5cf4b1651538d 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -4345,10 +4345,14 @@ VectorizationFactor LoopVectorizationPlanner::selectVectorizationFactor() { bool LoopVectorizationPlanner::isCandidateForEpilogueVectorization( ElementCount VF) const { - // Cross iteration phis such as reductions need special handling and are - // currently unsupported. - if (any_of(OrigLoop->getHeader()->phis(), - [&](PHINode &Phi) { return Legal->isFixedOrderRecurrence(&Phi); })) + // Cross iteration phis such as fixed-order recurrences and FMaxNum/FMinNum + // reductions need special handling and are currently unsupported. + if (any_of(OrigLoop->getHeader()->phis(), [&](PHINode &Phi) { + if (!Legal->isReductionVariable(&Phi)) + return Legal->isFixedOrderRecurrence(&Phi); + RecurKind RK = Legal->getRecurrenceDescriptor(&Phi).getRecurrenceKind(); + return RK == RecurKind::FMinNum || RK == RecurKind::FMaxNum; + })) return false; // Phis with uses outside of the loop require special handling and are @@ -8817,6 +8821,12 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes( // Adjust the recipes for any inloop reductions. adjustRecipesForReductions(Plan, RecipeBuilder, Range.Start); + // Apply mandatory transformation to handle FP maxnum/minnum reduction with + // NaNs if possible, bail out otherwise. + if (!VPlanTransforms::runPass(VPlanTransforms::handleMaxMinNumReductions, + *Plan)) + return nullptr; + // Transform recipes to abstract recipes if it is legal and beneficial and // clamp the range for better cost estimation. // TODO: Enable following transform when the EVL-version of extended-reduction diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 31aec77db63c1..2d50981690f41 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -9968,7 +9968,10 @@ BoUpSLP::getScalarsVectorizationLegality(ArrayRef VL, unsigned Depth, } SmallPtrSet Values(llvm::from_range, E->Scalars); if (all_of(VL, [&](Value *V) { - return isa(V) || Values.contains(V); + return isa(V) || Values.contains(V) || + (S.getOpcode() == Instruction::PHI && isa(V) && + LI->getLoopFor(S.getMainOp()->getParent()) && + isVectorized(V)); })) { LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n"); return ScalarsVectorizationLegality(S, /*IsLegal=*/false); @@ -23196,6 +23199,8 @@ class HorizontalReduction { case RecurKind::FindFirstIVUMin: case RecurKind::FindLastIVSMax: case RecurKind::FindLastIVUMax: + case RecurKind::FMaxNum: + case RecurKind::FMinNum: case RecurKind::FMaximumNum: case RecurKind::FMinimumNum: case RecurKind::None: @@ -23333,6 +23338,8 @@ class HorizontalReduction { case RecurKind::FindFirstIVUMin: case RecurKind::FindLastIVSMax: case RecurKind::FindLastIVUMax: + case RecurKind::FMaxNum: + case RecurKind::FMinNum: case RecurKind::FMaximumNum: case RecurKind::FMinimumNum: case RecurKind::None: @@ -23435,6 +23442,8 @@ class HorizontalReduction { case RecurKind::FindFirstIVUMin: case RecurKind::FindLastIVSMax: case RecurKind::FindLastIVUMax: + case RecurKind::FMaxNum: + case RecurKind::FMinNum: case RecurKind::FMaximumNum: case RecurKind::FMinimumNum: case RecurKind::None: diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp index b27a7ffeed208..66657b98b094b 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp @@ -84,6 +84,7 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) { return ResTy; } case Instruction::ICmp: + case Instruction::FCmp: case VPInstruction::ActiveLaneMask: assert(inferScalarType(R->getOperand(0)) == inferScalarType(R->getOperand(1)) && diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp index 52eecb000d0c2..a7a22e042aefc 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp @@ -628,3 +628,163 @@ void VPlanTransforms::attachCheckBlock(VPlan &Plan, Value *Cond, Term->addMetadata(LLVMContext::MD_prof, BranchWeights); } } + +bool VPlanTransforms::handleMaxMinNumReductions(VPlan &Plan) { + auto GetMinMaxCompareValue = [](VPReductionPHIRecipe *RedPhiR) -> VPValue * { + auto *MinMaxR = dyn_cast( + RedPhiR->getBackedgeValue()->getDefiningRecipe()); + if (!MinMaxR) + return nullptr; + + auto *RepR = dyn_cast(MinMaxR); + if (!isa(MinMaxR) && + !(RepR && isa(RepR->getUnderlyingInstr()))) + return nullptr; + +#ifndef NDEBUG + Intrinsic::ID RdxIntrinsicId = + RedPhiR->getRecurrenceKind() == RecurKind::FMaxNum ? Intrinsic::maxnum + : Intrinsic::minnum; + assert((isa(MinMaxR) && + cast(MinMaxR)->getVectorIntrinsicID() == + RdxIntrinsicId) || + (RepR && + cast(RepR->getUnderlyingInstr())->getIntrinsicID() == + RdxIntrinsicId) && + "Intrinsic did not match recurrence kind"); +#endif + + if (MinMaxR->getOperand(0) == RedPhiR) + return MinMaxR->getOperand(1); + + assert(MinMaxR->getOperand(1) == RedPhiR && + "Reduction phi operand expected"); + return MinMaxR->getOperand(0); + }; + + VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion(); + VPReductionPHIRecipe *RedPhiR = nullptr; + bool HasUnsupportedPhi = false; + for (auto &R : LoopRegion->getEntryBasicBlock()->phis()) { + if (isa(&R)) + continue; + auto *Cur = dyn_cast(&R); + if (!Cur) { + // TODO: Also support fixed-order recurrence phis. + HasUnsupportedPhi = true; + continue; + } + // For now, only a single reduction is supported. + // TODO: Support multiple MaxNum/MinNum reductions and other reductions. + if (RedPhiR) + return false; + if (Cur->getRecurrenceKind() != RecurKind::FMaxNum && + Cur->getRecurrenceKind() != RecurKind::FMinNum) { + HasUnsupportedPhi = true; + continue; + } + RedPhiR = Cur; + } + + if (!RedPhiR) + return true; + + // We won't be able to resume execution in the scalar tail, if there are + // unsupported header phis or there is no scalar tail at all, due to + // tail-folding. + if (HasUnsupportedPhi || !Plan.hasScalarTail()) + return false; + + VPValue *MinMaxOp = GetMinMaxCompareValue(RedPhiR); + if (!MinMaxOp) + return false; + + RecurKind RedPhiRK = RedPhiR->getRecurrenceKind(); + assert((RedPhiRK == RecurKind::FMaxNum || RedPhiRK == RecurKind::FMinNum) && + "unsupported reduction"); + + /// Check if the vector loop of \p Plan can early exit and restart + /// execution of last vector iteration in the scalar loop. This requires all + /// recipes up to early exit point be side-effect free as they are + /// re-executed. Currently we check that the loop is free of any recipe that + /// may write to memory. Expected to operate on an early VPlan w/o nested + /// regions. + for (VPBlockBase *VPB : vp_depth_first_shallow( + Plan.getVectorLoopRegion()->getEntryBasicBlock())) { + auto *VPBB = cast(VPB); + for (auto &R : *VPBB) { + if (R.mayWriteToMemory() && + !match(&R, m_BranchOnCount(m_VPValue(), m_VPValue()))) + return false; + } + } + + VPBasicBlock *LatchVPBB = LoopRegion->getExitingBasicBlock(); + VPBuilder Builder(LatchVPBB->getTerminator()); + auto *LatchExitingBranch = cast(LatchVPBB->getTerminator()); + assert(LatchExitingBranch->getOpcode() == VPInstruction::BranchOnCount && + "Unexpected terminator"); + auto *IsLatchExitTaken = + Builder.createICmp(CmpInst::ICMP_EQ, LatchExitingBranch->getOperand(0), + LatchExitingBranch->getOperand(1)); + + VPValue *IsNaN = Builder.createFCmp(CmpInst::FCMP_UNO, MinMaxOp, MinMaxOp); + VPValue *AnyNaN = Builder.createNaryOp(VPInstruction::AnyOf, {IsNaN}); + auto *AnyExitTaken = + Builder.createNaryOp(Instruction::Or, {AnyNaN, IsLatchExitTaken}); + Builder.createNaryOp(VPInstruction::BranchOnCond, AnyExitTaken); + LatchExitingBranch->eraseFromParent(); + + // If we exit early due to NaNs, compute the final reduction result based on + // the reduction phi at the beginning of the last vector iteration. + auto *RdxResult = find_singleton( + RedPhiR->users(), [](VPUser *U, bool) -> VPSingleDefRecipe * { + auto *VPI = dyn_cast(U); + if (VPI && VPI->getOpcode() == VPInstruction::ComputeReductionResult) + return VPI; + return nullptr; + }); + + auto *MiddleVPBB = Plan.getMiddleBlock(); + Builder.setInsertPoint(MiddleVPBB, MiddleVPBB->begin()); + auto *NewSel = + Builder.createSelect(AnyNaN, RedPhiR, RdxResult->getOperand(1)); + RdxResult->setOperand(1, NewSel); + + auto *ScalarPH = Plan.getScalarPreheader(); + // Update resume phis for inductions in the scalar preheader. If AnyNaN is + // true, the resume from the start of the last vector iteration via the + // canonical IV, otherwise from the original value. + for (auto &R : ScalarPH->phis()) { + auto *ResumeR = cast(&R); + VPValue *VecV = ResumeR->getOperand(0); + if (VecV == RdxResult) + continue; + if (auto *DerivedIV = dyn_cast(VecV)) { + if (DerivedIV->getNumUsers() == 1 && + DerivedIV->getOperand(1) == &Plan.getVectorTripCount()) { + auto *NewSel = Builder.createSelect(AnyNaN, Plan.getCanonicalIV(), + &Plan.getVectorTripCount()); + DerivedIV->moveAfter(&*Builder.getInsertPoint()); + DerivedIV->setOperand(1, NewSel); + continue; + } + } + // Bail out and abandon the current, partially modified, VPlan if we + // encounter resume phi that cannot be updated yet. + if (VecV != &Plan.getVectorTripCount()) { + LLVM_DEBUG(dbgs() << "Found resume phi we cannot update for VPlan with " + "FMaxNum/FMinNum reduction.\n"); + return false; + } + auto *NewSel = Builder.createSelect(AnyNaN, Plan.getCanonicalIV(), VecV); + ResumeR->setOperand(0, NewSel); + } + + auto *MiddleTerm = MiddleVPBB->getTerminator(); + Builder.setInsertPoint(MiddleTerm); + VPValue *MiddleCond = MiddleTerm->getOperand(0); + VPValue *NewCond = Builder.createAnd(MiddleCond, Builder.createNot(AnyNaN)); + MiddleTerm->setOperand(0, NewCond); + return true; +} diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 1664bcc3881aa..57b713d3dfcb9 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -587,6 +587,7 @@ Value *VPInstruction::generate(VPTransformState &State) { Value *Op = State.get(getOperand(0), vputils::onlyFirstLaneUsed(this)); return Builder.CreateFreeze(Op, Name); } + case Instruction::FCmp: case Instruction::ICmp: { bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this); Value *A = State.get(getOperand(0), OnlyFirstLaneUsed); @@ -860,7 +861,7 @@ Value *VPInstruction::generate(VPTransformState &State) { Value *Res = State.get(getOperand(0)); for (VPValue *Op : drop_begin(operands())) Res = Builder.CreateOr(Res, State.get(Op)); - return Builder.CreateOrReduce(Res); + return State.VF.isScalar() ? Res : Builder.CreateOrReduce(Res); } case VPInstruction::FirstActiveLane: { if (getNumOperands() == 1) { @@ -1033,6 +1034,7 @@ bool VPInstruction::opcodeMayReadOrWriteFromMemory() const { switch (getOpcode()) { case Instruction::ExtractElement: case Instruction::Freeze: + case Instruction::FCmp: case Instruction::ICmp: case Instruction::Select: case VPInstruction::AnyOf: @@ -1068,6 +1070,7 @@ bool VPInstruction::onlyFirstLaneUsed(const VPValue *Op) const { return Op == getOperand(1); case Instruction::PHI: return true; + case Instruction::FCmp: case Instruction::ICmp: case Instruction::Select: case Instruction::Or: @@ -1100,6 +1103,7 @@ bool VPInstruction::onlyFirstPartUsed(const VPValue *Op) const { switch (getOpcode()) { default: return false; + case Instruction::FCmp: case Instruction::ICmp: case Instruction::Select: return vputils::onlyFirstPartUsed(this); @@ -1786,7 +1790,7 @@ bool VPIRFlags::flagsValidForOpcode(unsigned Opcode) const { return Opcode == Instruction::ZExt; break; case OperationType::Cmp: - return Opcode == Instruction::ICmp; + return Opcode == Instruction::FCmp || Opcode == Instruction::ICmp; case OperationType::Other: return true; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index 6a3b3e6e41955..f7c1c10185c68 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -3252,9 +3252,10 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF, return; // Convert InterleaveGroup \p R to a single VPWidenLoadRecipe. - auto NarrowOp = [](VPValue *V) -> VPValue * { + SmallPtrSet NarrowedOps; + auto NarrowOp = [&NarrowedOps](VPValue *V) -> VPValue * { auto *R = V->getDefiningRecipe(); - if (!R) + if (!R || NarrowedOps.contains(V)) return V; if (auto *LoadGroup = dyn_cast(R)) { // Narrow interleave group to wide load, as transformed VPlan will only @@ -3264,6 +3265,7 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF, LoadGroup->getAddr(), LoadGroup->getMask(), /*Consecutive=*/true, /*Reverse=*/false, {}, LoadGroup->getDebugLoc()); L->insertBefore(LoadGroup); + NarrowedOps.insert(L); return L; } @@ -3271,6 +3273,7 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF, assert(RepR->isSingleScalar() && isa(RepR->getUnderlyingInstr()) && "must be a single scalar load"); + NarrowedOps.insert(RepR); return RepR; } auto *WideLoad = cast(R); @@ -3281,6 +3284,7 @@ void VPlanTransforms::narrowInterleaveGroups(VPlan &Plan, ElementCount VF, WideLoad->operands(), /*IsUniform*/ true, /*Mask*/ nullptr, *WideLoad); N->insertBefore(WideLoad); + NarrowedOps.insert(N); return N; }; diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h index 870b1bb68b79a..c3fb359d1429a 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h @@ -99,6 +99,12 @@ struct VPlanTransforms { /// not valid. static bool adjustFixedOrderRecurrences(VPlan &Plan, VPBuilder &Builder); + /// Check if \p Plan contains any FMaxNum or FMinNum reductions. If they do, + /// try to update the vector loop to exit early if any input is NaN and resume + /// executing in the scalar loop to handle the NaNs there. Return false if + /// this attempt was unsuccessful. + static bool handleMaxMinNumReductions(VPlan &Plan); + /// Clear NSW/NUW flags from reduction instructions if necessary. static void clearReductionWrapFlags(VPlan &Plan); diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index fe8d74c43dfdc..ea9cbed0117b9 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -74,7 +74,7 @@ class VectorCombine { const DataLayout *DL, TTI::TargetCostKind CostKind, bool TryEarlyFoldsOnly) : F(F), Builder(F.getContext(), InstSimplifyFolder(*DL)), TTI(TTI), - DT(DT), AA(AA), AC(AC), DL(DL), CostKind(CostKind), + DT(DT), AA(AA), AC(AC), DL(DL), CostKind(CostKind), SQ(*DL), TryEarlyFoldsOnly(TryEarlyFoldsOnly) {} bool run(); @@ -88,6 +88,7 @@ class VectorCombine { AssumptionCache &AC; const DataLayout *DL; TTI::TargetCostKind CostKind; + const SimplifyQuery SQ; /// If true, only perform beneficial early IR transforms. Do not introduce new /// vector operations. @@ -1185,17 +1186,18 @@ bool VectorCombine::scalarizeOpOrCmp(Instruction &I) { // Fold the vector constants in the original vectors into a new base vector to // get more accurate cost modelling. Value *NewVecC = nullptr; - TargetFolder Folder(*DL); if (CI) - NewVecC = Folder.FoldCmp(CI->getPredicate(), VecCs[0], VecCs[1]); + NewVecC = simplifyCmpInst(CI->getPredicate(), VecCs[0], VecCs[1], SQ); else if (UO) NewVecC = - Folder.FoldUnOpFMF(UO->getOpcode(), VecCs[0], UO->getFastMathFlags()); + simplifyUnOp(UO->getOpcode(), VecCs[0], UO->getFastMathFlags(), SQ); else if (BO) - NewVecC = Folder.FoldBinOp(BO->getOpcode(), VecCs[0], VecCs[1]); - else if (II->arg_size() == 2) - NewVecC = Folder.FoldBinaryIntrinsic(II->getIntrinsicID(), VecCs[0], - VecCs[1], II->getType(), &I); + NewVecC = simplifyBinOp(BO->getOpcode(), VecCs[0], VecCs[1], SQ); + else if (II) + NewVecC = simplifyCall(II, II->getCalledOperand(), VecCs, SQ); + + if (!NewVecC) + return false; // Get cost estimate for the insert element. This cost will factor into // both sequences. @@ -1203,6 +1205,7 @@ bool VectorCombine::scalarizeOpOrCmp(Instruction &I) { InstructionCost NewCost = ScalarOpCost + TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind, *Index, NewVecC); + for (auto [Idx, Op, VecC, Scalar] : enumerate(Ops, VecCs, ScalarOps)) { if (!Scalar || (II && isVectorIntrinsicWithScalarOpAtArg( II->getIntrinsicID(), Idx, &TTI))) @@ -1247,15 +1250,6 @@ bool VectorCombine::scalarizeOpOrCmp(Instruction &I) { if (auto *ScalarInst = dyn_cast(Scalar)) ScalarInst->copyIRFlags(&I); - // Create a new base vector if the constant folding failed. - if (!NewVecC) { - if (CI) - NewVecC = Builder.CreateCmp(CI->getPredicate(), VecCs[0], VecCs[1]); - else if (UO || BO) - NewVecC = Builder.CreateNAryOp(Opcode, VecCs); - else - NewVecC = Builder.CreateIntrinsic(VecTy, II->getIntrinsicID(), VecCs); - } Value *Insert = Builder.CreateInsertElement(NewVecC, Scalar, *Index); replaceValue(I, *Insert); return true; @@ -1835,12 +1829,19 @@ bool VectorCombine::scalarizeExtExtract(Instruction &I) { IntegerType::get(SrcTy->getContext(), DL->getTypeSizeInBits(SrcTy))); uint64_t SrcEltSizeInBits = DL->getTypeSizeInBits(SrcTy->getElementType()); uint64_t EltBitMask = (1ull << SrcEltSizeInBits) - 1; + uint64_t TotalBits = DL->getTypeSizeInBits(SrcTy); + Type *PackedTy = IntegerType::get(SrcTy->getContext(), TotalBits); + Value *Mask = ConstantInt::get(PackedTy, EltBitMask); for (User *U : Ext->users()) { auto *Extract = cast(U); uint64_t Idx = cast(Extract->getIndexOperand())->getZExtValue(); - Value *LShr = Builder.CreateLShr(ScalarV, Idx * SrcEltSizeInBits); - Value *And = Builder.CreateAnd(LShr, EltBitMask); + uint64_t ShiftAmt = + DL->isBigEndian() + ? (TotalBits - SrcEltSizeInBits - Idx * SrcEltSizeInBits) + : (Idx * SrcEltSizeInBits); + Value *LShr = Builder.CreateLShr(ScalarV, ShiftAmt); + Value *And = Builder.CreateAnd(LShr, Mask); U->replaceAllUsesWith(And); } return true; diff --git a/llvm/test/Analysis/CostModel/AArch64/reduce-and.ll b/llvm/test/Analysis/CostModel/AArch64/reduce-and.ll index b484f8f6c60ba..21e0356fd7321 100644 --- a/llvm/test/Analysis/CostModel/AArch64/reduce-and.ll +++ b/llvm/test/Analysis/CostModel/AArch64/reduce-and.ll @@ -13,8 +13,8 @@ define void @reduce() { ; CHECK-NEXT: Cost Model: Found costs of 3 for: %V32 = call i1 @llvm.vector.reduce.and.v32i1(<32 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 5 for: %V64 = call i1 @llvm.vector.reduce.and.v64i1(<64 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 9 for: %V128 = call i1 @llvm.vector.reduce.and.v128i1(<128 x i1> undef) -; CHECK-NEXT: Cost Model: Found costs of 0 for: %V1i8 = call i8 @llvm.vector.reduce.and.v1i8(<1 x i8> undef) -; CHECK-NEXT: Cost Model: Found costs of 4 for: %V3i8 = call i8 @llvm.vector.reduce.and.v3i8(<3 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:2 CodeSize:1 Lat:2 SizeLat:2 for: %V1i8 = call i8 @llvm.vector.reduce.and.v1i8(<1 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:5 Lat:6 SizeLat:6 for: %V3i8 = call i8 @llvm.vector.reduce.and.v3i8(<3 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 7 for: %V4i8 = call i8 @llvm.vector.reduce.and.v4i8(<4 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 15 for: %V8i8 = call i8 @llvm.vector.reduce.and.v8i8(<8 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 17 for: %V16i8 = call i8 @llvm.vector.reduce.and.v16i8(<16 x i8> undef) diff --git a/llvm/test/Analysis/CostModel/AArch64/reduce-or.ll b/llvm/test/Analysis/CostModel/AArch64/reduce-or.ll index 519b8ecf6dc76..27dd42297bfab 100644 --- a/llvm/test/Analysis/CostModel/AArch64/reduce-or.ll +++ b/llvm/test/Analysis/CostModel/AArch64/reduce-or.ll @@ -13,8 +13,8 @@ define void @reduce() { ; CHECK-NEXT: Cost Model: Found costs of 3 for: %V32 = call i1 @llvm.vector.reduce.or.v32i1(<32 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 5 for: %V64 = call i1 @llvm.vector.reduce.or.v64i1(<64 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 9 for: %V128 = call i1 @llvm.vector.reduce.or.v128i1(<128 x i1> undef) -; CHECK-NEXT: Cost Model: Found costs of 0 for: %V1i8 = call i8 @llvm.vector.reduce.or.v1i8(<1 x i8> undef) -; CHECK-NEXT: Cost Model: Found costs of 4 for: %V3i8 = call i8 @llvm.vector.reduce.or.v3i8(<3 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:2 CodeSize:1 Lat:2 SizeLat:2 for: %V1i8 = call i8 @llvm.vector.reduce.or.v1i8(<1 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:5 Lat:6 SizeLat:6 for: %V3i8 = call i8 @llvm.vector.reduce.or.v3i8(<3 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 7 for: %V4i8 = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 15 for: %V8i8 = call i8 @llvm.vector.reduce.or.v8i8(<8 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 17 for: %V16i8 = call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> undef) diff --git a/llvm/test/Analysis/CostModel/AArch64/reduce-xor.ll b/llvm/test/Analysis/CostModel/AArch64/reduce-xor.ll index 2a8609d2f418b..826605450a2d8 100644 --- a/llvm/test/Analysis/CostModel/AArch64/reduce-xor.ll +++ b/llvm/test/Analysis/CostModel/AArch64/reduce-xor.ll @@ -13,8 +13,8 @@ define void @reduce() { ; CHECK-NEXT: Cost Model: Found costs of 3 for: %V32 = call i1 @llvm.vector.reduce.xor.v32i1(<32 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 5 for: %V64 = call i1 @llvm.vector.reduce.xor.v64i1(<64 x i1> undef) ; CHECK-NEXT: Cost Model: Found costs of 9 for: %V128 = call i1 @llvm.vector.reduce.xor.v128i1(<128 x i1> undef) -; CHECK-NEXT: Cost Model: Found costs of 0 for: %V1i8 = call i8 @llvm.vector.reduce.xor.v1i8(<1 x i8> undef) -; CHECK-NEXT: Cost Model: Found costs of 4 for: %V3i8 = call i8 @llvm.vector.reduce.xor.v3i8(<3 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:2 CodeSize:1 Lat:2 SizeLat:2 for: %V1i8 = call i8 @llvm.vector.reduce.xor.v1i8(<1 x i8> undef) +; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:5 Lat:6 SizeLat:6 for: %V3i8 = call i8 @llvm.vector.reduce.xor.v3i8(<3 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 7 for: %V4i8 = call i8 @llvm.vector.reduce.xor.v4i8(<4 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 15 for: %V8i8 = call i8 @llvm.vector.reduce.xor.v8i8(<8 x i8> undef) ; CHECK-NEXT: Cost Model: Found costs of 17 for: %V16i8 = call i8 @llvm.vector.reduce.xor.v16i8(<16 x i8> undef) diff --git a/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll b/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll index 41c272291d7ca..4579acb9b3555 100644 --- a/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll +++ b/llvm/test/Analysis/CostModel/AArch64/shuffle-other.ll @@ -93,36 +93,36 @@ define void @insert_subvec() { ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i8_2_1 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i8_2_2 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i8_2_3 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:3 Lat:6 SizeLat:6 for: %v8i8_2_05 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:8 CodeSize:4 Lat:8 SizeLat:8 for: %v8i8_2_05 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i8_4_0 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i8_4_1 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i8_4_2 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i8_4_3 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:14 CodeSize:7 Lat:14 SizeLat:14 for: %v16i8_4_05 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:16 CodeSize:8 Lat:16 SizeLat:16 for: %v16i8_4_05 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v4i16_2_0 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v4i16_2_1 = shufflevector <4 x i16> undef, <4 x i16> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i16_2_0 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i16_2_1 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i16_2_2 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i16_2_3 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:3 Lat:6 SizeLat:6 for: %v8i16_2_05 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:8 CodeSize:4 Lat:8 SizeLat:8 for: %v8i16_2_05 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i16_4_0 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i16_4_1 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i16_4_2 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i16_4_3 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:14 CodeSize:7 Lat:14 SizeLat:14 for: %v16i16_4_05 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:16 CodeSize:8 Lat:16 SizeLat:16 for: %v16i16_4_05 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v4i32_2_0 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v4i32_2_1 = shufflevector <4 x i32> undef, <4 x i32> undef, <4 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i32_2_0 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i32_2_1 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i32_2_2 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v8i32_2_3 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:6 CodeSize:3 Lat:6 SizeLat:6 for: %v8i32_2_05 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:8 CodeSize:4 Lat:8 SizeLat:8 for: %v8i32_2_05 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i32_4_0 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i32_4_1 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i32_4_2 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v16i32_4_3 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %v16i32_4_05 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:16 CodeSize:8 Lat:16 SizeLat:16 for: %v16i32_4_05 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void ; %v4i8_2_0 = shufflevector <4 x i8> undef, <4 x i8> undef, <4 x i32> @@ -369,7 +369,7 @@ define void @multipart() { ; CHECK-NEXT: Cost Model: Found costs of 4 for: %v32idrev = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 16 for: %v32many = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 16 for: %v32many2 = shufflevector <16 x i32> undef, <16 x i32> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:8 CodeSize:4 Lat:8 SizeLat:8 for: %v323 = shufflevector <3 x i32> undef, <3 x i32> undef, <3 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %v323 = shufflevector <3 x i32> undef, <3 x i32> undef, <3 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v64a = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> ; CHECK-NEXT: Cost Model: Found costs of 1 for: %v64b = shufflevector <2 x i64> undef, <2 x i64> undef, <2 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found costs of 2 for: %v64ab = shufflevector <4 x i64> undef, <4 x i64> undef, <4 x i32> @@ -408,10 +408,10 @@ define void @vst3(ptr %p) { ; CHECK-LABEL: 'vst3' ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v8i8 = shufflevector <4 x i8> undef, <4 x i8> undef, <6 x i32> ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v16i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <12 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:120 CodeSize:60 Lat:120 SizeLat:120 for: %v32i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <24 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:128 CodeSize:64 Lat:128 SizeLat:128 for: %v32i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <24 x i32> ; CHECK-NEXT: Cost Model: Found costs of 48 for: %v64i8 = shufflevector <32 x i8> undef, <32 x i8> undef, <48 x i32> ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v8i16 = shufflevector <4 x i16> undef, <4 x i16> undef, <6 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:56 CodeSize:28 Lat:56 SizeLat:56 for: %v16i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <12 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %v16i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <12 x i32> ; CHECK-NEXT: Cost Model: Found costs of 24 for: %v32i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <24 x i32> ; CHECK-NEXT: Cost Model: Found costs of 48 for: %v64i16 = shufflevector <32 x i16> undef, <32 x i16> undef, <48 x i32> ; CHECK-NEXT: Cost Model: Found costs of 5 for: %v8i32 = shufflevector <4 x i32> undef, <4 x i32> undef, <6 x i32> @@ -452,10 +452,10 @@ define void @vst4(ptr %p) { ; CHECK-LABEL: 'vst4' ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v8i8 = shufflevector <8 x i8> undef, <8 x i8> undef, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v16i8 = shufflevector <16 x i8> undef, <16 x i8> undef, <16 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:120 CodeSize:60 Lat:120 SizeLat:120 for: %v32i8 = shufflevector <32 x i8> undef, <32 x i8> undef, <32 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:128 CodeSize:64 Lat:128 SizeLat:128 for: %v32i8 = shufflevector <32 x i8> undef, <32 x i8> undef, <32 x i32> ; CHECK-NEXT: Cost Model: Found costs of 64 for: %v64i8 = shufflevector <64 x i8> undef, <64 x i8> undef, <64 x i32> ; CHECK-NEXT: Cost Model: Found costs of 8 for: %v8i16 = shufflevector <8 x i16> undef, <8 x i16> undef, <8 x i32> -; CHECK-NEXT: Cost Model: Found costs of RThru:56 CodeSize:28 Lat:56 SizeLat:56 for: %v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %v16i16 = shufflevector <16 x i16> undef, <16 x i16> undef, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of 32 for: %v32i16 = shufflevector <32 x i16> undef, <32 x i16> undef, <32 x i32> ; CHECK-NEXT: Cost Model: Found costs of 64 for: %v64i16 = shufflevector <64 x i16> undef, <64 x i16> undef, <64 x i32> ; CHECK-NEXT: Cost Model: Found costs of 2 for: %v8i32 = shufflevector <8 x i32> undef, <8 x i32> undef, <8 x i32> diff --git a/llvm/test/Analysis/CostModel/AArch64/shuffle-select.ll b/llvm/test/Analysis/CostModel/AArch64/shuffle-select.ll index 09f116f01ec77..4a003a0085c23 100644 --- a/llvm/test/Analysis/CostModel/AArch64/shuffle-select.ll +++ b/llvm/test/Analysis/CostModel/AArch64/shuffle-select.ll @@ -5,7 +5,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define <8 x i8> @sel_v8i8(<8 x i8> %v0, <8 x i8> %v1) { ; CHECK-LABEL: 'sel_v8i8' -; CHECK-NEXT: Cost Model: Found costs of RThru:28 CodeSize:14 Lat:28 SizeLat:28 for: %tmp0 = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:32 CodeSize:16 Lat:32 SizeLat:32 for: %tmp0 = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret <8 x i8> %tmp0 ; %tmp0 = shufflevector <8 x i8> %v0, <8 x i8> %v1, <8 x i32> @@ -14,7 +14,7 @@ define <8 x i8> @sel_v8i8(<8 x i8> %v0, <8 x i8> %v1) { define <16 x i8> @sel_v16i8(<16 x i8> %v0, <16 x i8> %v1) { ; CHECK-LABEL: 'sel_v16i8' -; CHECK-NEXT: Cost Model: Found costs of RThru:60 CodeSize:30 Lat:60 SizeLat:60 for: %tmp0 = shufflevector <16 x i8> %v0, <16 x i8> %v1, <16 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %tmp0 = shufflevector <16 x i8> %v0, <16 x i8> %v1, <16 x i32> ; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret <16 x i8> %tmp0 ; %tmp0 = shufflevector <16 x i8> %v0, <16 x i8> %v1, <16 x i32> @@ -32,7 +32,7 @@ define <4 x i16> @sel_v4i16(<4 x i16> %v0, <4 x i16> %v1) { define <8 x i16> @sel_v8i16(<8 x i16> %v0, <8 x i16> %v1) { ; CHECK-LABEL: 'sel_v8i16' -; CHECK-NEXT: Cost Model: Found costs of RThru:28 CodeSize:14 Lat:28 SizeLat:28 for: %tmp0 = shufflevector <8 x i16> %v0, <8 x i16> %v1, <8 x i32> +; CHECK-NEXT: Cost Model: Found costs of RThru:32 CodeSize:16 Lat:32 SizeLat:32 for: %tmp0 = shufflevector <8 x i16> %v0, <8 x i16> %v1, <8 x i32> ; CHECK-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret <8 x i16> %tmp0 ; %tmp0 = shufflevector <8 x i16> %v0, <8 x i16> %v1, <8 x i32> diff --git a/llvm/test/Analysis/CostModel/AArch64/sve-intrinsics.ll b/llvm/test/Analysis/CostModel/AArch64/sve-intrinsics.ll index ec84c58bf9681..fa889cc12dc4f 100644 --- a/llvm/test/Analysis/CostModel/AArch64/sve-intrinsics.ll +++ b/llvm/test/Analysis/CostModel/AArch64/sve-intrinsics.ll @@ -7,15 +7,15 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define void @vector_insert_extract( %v0, %v1, <16 x i32> %v2) { ; CHECK-VSCALE-1-LABEL: 'vector_insert_extract' -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:54 CodeSize:27 Lat:54 SizeLat:54 for: %extract_fixed_from_scalable = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( %v0, i64 0) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:54 CodeSize:27 Lat:54 SizeLat:54 for: %insert_fixed_into_scalable = call @llvm.vector.insert.nxv4i32.v16i32( %v0, <16 x i32> %v2, i64 0) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %extract_fixed_from_scalable = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( %v0, i64 0) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %insert_fixed_into_scalable = call @llvm.vector.insert.nxv4i32.v16i32( %v0, <16 x i32> %v2, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %extract_scalable_from_scalable = call @llvm.vector.extract.nxv4i32.nxv16i32( %v1, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %insert_scalable_into_scalable = call @llvm.vector.insert.nxv16i32.nxv4i32( %v1, %v0, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void ; ; CHECK-VSCALE-2-LABEL: 'vector_insert_extract' -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:54 CodeSize:27 Lat:54 SizeLat:54 for: %extract_fixed_from_scalable = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( %v0, i64 0) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:54 CodeSize:27 Lat:54 SizeLat:54 for: %insert_fixed_into_scalable = call @llvm.vector.insert.nxv4i32.v16i32( %v0, <16 x i32> %v2, i64 0) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %extract_fixed_from_scalable = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( %v0, i64 0) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:64 CodeSize:32 Lat:64 SizeLat:64 for: %insert_fixed_into_scalable = call @llvm.vector.insert.nxv4i32.v16i32( %v0, <16 x i32> %v2, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %extract_scalable_from_scalable = call @llvm.vector.extract.nxv4i32.nxv16i32( %v1, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %insert_scalable_into_scalable = call @llvm.vector.insert.nxv16i32.nxv4i32( %v1, %v0, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void @@ -44,7 +44,7 @@ define void @vector_insert_extract_idxzero_128b() #1 { ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 0 for: %extract_legal_fixed_from_scalable = call <2 x double> @llvm.vector.extract.v2f64.nxv2f64( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %insert_nxv16i1_nxv2i1 = call @llvm.vector.insert.nxv16i1.nxv2i1( undef, undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %extract_nxv4i1_nxv16i1 = call @llvm.vector.extract.nxv4i1.nxv16i1( undef, i64 0) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:42 CodeSize:28 Lat:42 SizeLat:42 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:48 CodeSize:32 Lat:48 SizeLat:48 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:4 CodeSize:2 Lat:4 SizeLat:4 for: %insert_v2f32_nxv2f32 = call @llvm.vector.insert.nxv2f32.v2f32( undef, <2 x float> undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %extract_v4f16_nxv4f16 = call <4 x half> @llvm.vector.extract.v4f16.nxv4f16( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %insert_nxv2f32_nxv4f32 = call @llvm.vector.insert.nxv4f32.nxv2f32( undef, undef, i64 0) @@ -56,7 +56,7 @@ define void @vector_insert_extract_idxzero_128b() #1 { ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 0 for: %extract_legal_fixed_from_scalable = call <2 x double> @llvm.vector.extract.v2f64.nxv2f64( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %insert_nxv16i1_nxv2i1 = call @llvm.vector.insert.nxv16i1.nxv2i1( undef, undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %extract_nxv4i1_nxv16i1 = call @llvm.vector.extract.nxv4i1.nxv16i1( undef, i64 0) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:42 CodeSize:28 Lat:42 SizeLat:42 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:48 CodeSize:32 Lat:48 SizeLat:48 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:4 CodeSize:2 Lat:4 SizeLat:4 for: %insert_v2f32_nxv2f32 = call @llvm.vector.insert.nxv2f32.v2f32( undef, <2 x float> undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %extract_v4f16_nxv4f16 = call <4 x half> @llvm.vector.extract.v4f16.nxv4f16( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %insert_nxv2f32_nxv4f32 = call @llvm.vector.insert.nxv4f32.nxv2f32( undef, undef, i64 0) @@ -101,7 +101,7 @@ define void @vector_insert_extract_idxzero_256b() #2 { ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 0 for: %extract_legal_fixed_from_scalable = call <8 x float> @llvm.vector.extract.v8f32.nxv4f32( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %insert_nxv16i1_nxv2i1 = call @llvm.vector.insert.nxv16i1.nxv2i1( undef, undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %extract_nxv4i1_nxv16i1 = call @llvm.vector.extract.nxv4i1.nxv16i1( undef, i64 0) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:42 CodeSize:28 Lat:42 SizeLat:42 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:48 CodeSize:32 Lat:48 SizeLat:48 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:4 CodeSize:2 Lat:4 SizeLat:4 for: %insert_v2f32_nxv2f32 = call @llvm.vector.insert.nxv2f32.v2f32( undef, <2 x float> undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %extract_v4f16_nxv4f16 = call <4 x half> @llvm.vector.extract.v4f16.nxv4f16( undef, i64 0) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 1 for: %insert_nxv2f32_nxv4f32 = call @llvm.vector.insert.nxv4f32.nxv2f32( undef, undef, i64 0) @@ -113,7 +113,7 @@ define void @vector_insert_extract_idxzero_256b() #2 { ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 0 for: %extract_legal_fixed_from_scalable = call <8 x float> @llvm.vector.extract.v8f32.nxv4f32( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %insert_nxv16i1_nxv2i1 = call @llvm.vector.insert.nxv16i1.nxv2i1( undef, undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %extract_nxv4i1_nxv16i1 = call @llvm.vector.extract.nxv4i1.nxv16i1( undef, i64 0) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:42 CodeSize:28 Lat:42 SizeLat:42 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:48 CodeSize:32 Lat:48 SizeLat:48 for: %extract_v8i1_nxv8i1 = call <8 x i1> @llvm.vector.extract.v8i1.nxv8i1( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:4 CodeSize:2 Lat:4 SizeLat:4 for: %insert_v2f32_nxv2f32 = call @llvm.vector.insert.nxv2f32.v2f32( undef, <2 x float> undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:12 CodeSize:6 Lat:12 SizeLat:12 for: %extract_v4f16_nxv4f16 = call <4 x half> @llvm.vector.extract.v4f16.nxv4f16( undef, i64 0) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 1 for: %insert_nxv2f32_nxv4f32 = call @llvm.vector.insert.nxv4f32.nxv2f32( undef, undef, i64 0) @@ -1364,34 +1364,34 @@ define void @match() #3 { ; CHECK-VSCALE-1-LABEL: 'match' ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 4 for: %match_nxv16i8_v16i8 = call @llvm.experimental.vector.match.nxv16i8.v16i8( undef, <16 x i8> undef, undef) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 4 for: %match_nxv8i16_v8i16 = call @llvm.experimental.vector.match.nxv8i16.v8i16( undef, <8 x i16> undef, undef) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 14 for: %match_v16i8_v16i8 = call <16 x i1> @llvm.experimental.vector.match.v16i8.v16i8(<16 x i8> undef, <16 x i8> undef, <16 x i1> undef) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of 14 for: %match_v8i16_v8i16 = call <8 x i1> @llvm.experimental.vector.match.v8i16.v8i16(<8 x i16> undef, <8 x i16> undef, <8 x i1> undef) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) -; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) +; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) ; CHECK-VSCALE-1-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void ; ; CHECK-VSCALE-2-LABEL: 'match' ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 4 for: %match_nxv16i8_v16i8 = call @llvm.experimental.vector.match.nxv16i8.v16i8( undef, <16 x i8> undef, undef) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 4 for: %match_nxv8i16_v8i16 = call @llvm.experimental.vector.match.nxv8i16.v8i16( undef, <8 x i16> undef, undef) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 14 for: %match_v16i8_v16i8 = call <16 x i1> @llvm.experimental.vector.match.v16i8.v16i8(<16 x i8> undef, <16 x i8> undef, <16 x i1> undef) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of 14 for: %match_v8i16_v8i16 = call <8 x i1> @llvm.experimental.vector.match.v8i16.v8i16(<8 x i16> undef, <8 x i16> undef, <8 x i1> undef) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) -; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) +; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) ; CHECK-VSCALE-2-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void ; ; TYPE_BASED_ONLY-LABEL: 'match' ; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of 4 for: %match_nxv16i8_v16i8 = call @llvm.experimental.vector.match.nxv16i8.v16i8( undef, <16 x i8> undef, undef) ; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of 4 for: %match_nxv8i16_v8i16 = call @llvm.experimental.vector.match.nxv8i16.v8i16( undef, <8 x i16> undef, undef) -; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) -; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) +; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_nxv4i32_v4i32 = call @llvm.experimental.vector.match.nxv4i32.v4i32( undef, <4 x i32> undef, undef) +; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_nxv2i64_v2i64 = call @llvm.experimental.vector.match.nxv2i64.v2i64( undef, <2 x i64> undef, undef) ; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of 14 for: %match_v16i8_v16i8 = call <16 x i1> @llvm.experimental.vector.match.v16i8.v16i8(<16 x i8> undef, <16 x i8> undef, <16 x i1> undef) ; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of 14 for: %match_v8i16_v8i16 = call <8 x i1> @llvm.experimental.vector.match.v8i16.v8i16(<8 x i16> undef, <8 x i16> undef, <8 x i1> undef) -; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:21 CodeSize:17 Lat:21 SizeLat:21 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) -; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:11 CodeSize:9 Lat:11 SizeLat:11 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) +; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:29 CodeSize:21 Lat:29 SizeLat:29 for: %match_v4i32_v4i32 = call <4 x i1> @llvm.experimental.vector.match.v4i32.v4i32(<4 x i32> undef, <4 x i32> undef, <4 x i1> undef) +; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:15 CodeSize:11 Lat:15 SizeLat:15 for: %match_v2i64_v2i64 = call <2 x i1> @llvm.experimental.vector.match.v2i64.v2i64(<2 x i64> undef, <2 x i64> undef, <2 x i1> undef) ; TYPE_BASED_ONLY-NEXT: Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void ; diff --git a/llvm/test/Analysis/CostModel/RISCV/cast.ll b/llvm/test/Analysis/CostModel/RISCV/cast.ll index bdd8540a2c475..e64bce2d9c9e5 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cast.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py -; RUN: opt < %s -mtriple=riscv32 -mattr=+v,+zfh,+zvfh -passes="print" -cost-kind=throughput -intrinsic-cost-strategy=type-based-intrinsic-cost 2>&1 -disable-output | FileCheck %s --check-prefixes=CHECK,RV32 -; RUN: opt < %s -mtriple=riscv64 -mattr=+v,+zfh,+zvfh -passes="print" -cost-kind=throughput -intrinsic-cost-strategy=type-based-intrinsic-cost 2>&1 -disable-output | FileCheck %s --check-prefixes=CHECK,RV64 +; RUN: opt < %s -mtriple=riscv32 -mattr=+v,+zfh,+zvfh -passes="print" -cost-kind=throughput -intrinsic-cost-strategy=type-based-intrinsic-cost 2>&1 -disable-output | FileCheck %s --check-prefixes=CHECK,ZVE64D +; RUN: opt < %s -mtriple=riscv64 -mattr=+v,+zfh,+zvfh -passes="print" -cost-kind=throughput -intrinsic-cost-strategy=type-based-intrinsic-cost 2>&1 -disable-output | FileCheck %s --check-prefixes=CHECK,ZVE64D +; RUN: opt < %s -mtriple=riscv64 -mattr=+zvl128b,+zve64x -passes="print" -cost-kind=throughput -intrinsic-cost-strategy=type-based-intrinsic-cost 2>&1 -disable-output | FileCheck %s --check-prefixes=CHECK,ZVE64X define void @sext() { ; CHECK-LABEL: 'sext' @@ -2021,92 +2022,179 @@ define void @trunc() { } define void @fpext() { -; CHECK-LABEL: 'fpext' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f16_v2f32 = fpext <2 x half> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f16_v2f64 = fpext <2 x half> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2f64 = fpext <2 x float> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f16_v2f32 = call <2 x float> @llvm.vp.fpext.v2f32.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f16_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f16_v4f32 = fpext <4 x half> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f16_v4f64 = fpext <4 x half> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4f64 = fpext <4 x float> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f16_v4f32 = call <4 x float> @llvm.vp.fpext.v4f32.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f16_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f16_v8f32 = fpext <8 x half> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f16_v8f64 = fpext <8 x half> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8f64 = fpext <8 x float> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f16_v8f32 = call <8 x float> @llvm.vp.fpext.v8f32.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f16_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f16_v16f32 = fpext <16 x half> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f16_v16f64 = fpext <16 x half> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16f64 = fpext <16 x float> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f16_v16f32 = call <16 x float> @llvm.vp.fpext.v16f32.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f16_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f16_v32f32 = fpext <32 x half> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f16_v32f64 = fpext <32 x half> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32f64 = fpext <32 x float> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f16_v32f32 = call <32 x float> @llvm.vp.fpext.v32f32.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f16_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64f16_v64f32 = fpext <64 x half> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f16_v64f64 = fpext <64 x half> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64f64 = fpext <64 x float> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64f16_v64f32 = call <64 x float> @llvm.vp.fpext.v64f32.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f16_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128f16_v128f32 = fpext <128 x half> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128f16_v128f64 = fpext <128 x half> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128f64 = fpext <128 x float> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128f16_v128f32 = call <128 x float> @llvm.vp.fpext.v128f32.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128f16_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f16_nxv1f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f16_nxv1f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f16_nxv1f32 = call @llvm.vp.fpext.nxv1f32.nxv1f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f16_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f16_nxv2f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f16_nxv2f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f16_nxv2f32 = call @llvm.vp.fpext.nxv2f32.nxv2f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f16_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f16_nxv4f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f16_nxv4f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f16_nxv4f32 = call @llvm.vp.fpext.nxv4f32.nxv4f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f16_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f16_nxv8f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f16_nxv8f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f16_nxv8f32 = call @llvm.vp.fpext.nxv8f32.nxv8f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f16_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f16_nxv16f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f16_nxv16f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f16_nxv16f32 = call @llvm.vp.fpext.nxv16f32.nxv16f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f16_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32f16_nxv32f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f16_nxv32f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32f16_nxv32f32 = call @llvm.vp.fpext.nxv32f32.nxv32f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f16_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64f16_nxv64f32 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64f16_nxv64f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64f64 = fpext undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64f16_nxv64f32 = call @llvm.vp.fpext.nxv64f32.nxv64f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64f16_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'fpext' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f16_v2f32 = fpext <2 x half> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f16_v2f64 = fpext <2 x half> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2f64 = fpext <2 x float> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f16_v2f32 = call <2 x float> @llvm.vp.fpext.v2f32.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f16_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f16_v4f32 = fpext <4 x half> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f16_v4f64 = fpext <4 x half> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4f64 = fpext <4 x float> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f16_v4f32 = call <4 x float> @llvm.vp.fpext.v4f32.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f16_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f16_v8f32 = fpext <8 x half> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f16_v8f64 = fpext <8 x half> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8f64 = fpext <8 x float> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f16_v8f32 = call <8 x float> @llvm.vp.fpext.v8f32.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f16_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f16_v16f32 = fpext <16 x half> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f16_v16f64 = fpext <16 x half> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16f64 = fpext <16 x float> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f16_v16f32 = call <16 x float> @llvm.vp.fpext.v16f32.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f16_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f16_v32f32 = fpext <32 x half> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f16_v32f64 = fpext <32 x half> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32f64 = fpext <32 x float> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f16_v32f32 = call <32 x float> @llvm.vp.fpext.v32f32.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f16_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64f16_v64f32 = fpext <64 x half> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f16_v64f64 = fpext <64 x half> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64f64 = fpext <64 x float> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64f16_v64f32 = call <64 x float> @llvm.vp.fpext.v64f32.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f16_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128f16_v128f32 = fpext <128 x half> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128f16_v128f64 = fpext <128 x half> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128f64 = fpext <128 x float> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128f16_v128f32 = call <128 x float> @llvm.vp.fpext.v128f32.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128f16_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f16_nxv1f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f16_nxv1f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f16_nxv1f32 = call @llvm.vp.fpext.nxv1f32.nxv1f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f16_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f16_nxv2f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f16_nxv2f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f16_nxv2f32 = call @llvm.vp.fpext.nxv2f32.nxv2f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f16_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f16_nxv4f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f16_nxv4f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f16_nxv4f32 = call @llvm.vp.fpext.nxv4f32.nxv4f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f16_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f16_nxv8f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f16_nxv8f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f16_nxv8f32 = call @llvm.vp.fpext.nxv8f32.nxv8f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f16_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f16_nxv16f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f16_nxv16f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f16_nxv16f32 = call @llvm.vp.fpext.nxv16f32.nxv16f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f16_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32f16_nxv32f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f16_nxv32f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32f16_nxv32f32 = call @llvm.vp.fpext.nxv32f32.nxv32f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f16_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64f16_nxv64f32 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64f16_nxv64f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64f64 = fpext undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64f16_nxv64f32 = call @llvm.vp.fpext.nxv64f32.nxv64f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64f16_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'fpext' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f16_v2f32 = fpext <2 x half> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f16_v2f64 = fpext <2 x half> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2f64 = fpext <2 x float> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f16_v2f32 = call <2 x float> @llvm.vp.fpext.v2f32.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f16_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f16(<2 x half> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2f64 = call <2 x double> @llvm.vp.fpext.v2f64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f16_v4f32 = fpext <4 x half> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f16_v4f64 = fpext <4 x half> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f32_v4f64 = fpext <4 x float> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f16_v4f32 = call <4 x float> @llvm.vp.fpext.v4f32.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f16_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f16(<4 x half> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f32_v4f64 = call <4 x double> @llvm.vp.fpext.v4f64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f16_v8f32 = fpext <8 x half> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f16_v8f64 = fpext <8 x half> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f32_v8f64 = fpext <8 x float> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f16_v8f32 = call <8 x float> @llvm.vp.fpext.v8f32.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f16_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f16(<8 x half> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f32_v8f64 = call <8 x double> @llvm.vp.fpext.v8f64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f16_v16f32 = fpext <16 x half> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f16_v16f64 = fpext <16 x half> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f32_v16f64 = fpext <16 x float> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f16_v16f32 = call <16 x float> @llvm.vp.fpext.v16f32.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f16_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f16(<16 x half> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f32_v16f64 = call <16 x double> @llvm.vp.fpext.v16f64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f16_v32f32 = fpext <32 x half> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f16_v32f64 = fpext <32 x half> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f32_v32f64 = fpext <32 x float> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f16_v32f32 = call <32 x float> @llvm.vp.fpext.v32f32.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f16_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f16(<32 x half> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f32_v32f64 = call <32 x double> @llvm.vp.fpext.v32f64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f16_v64f32 = fpext <64 x half> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f16_v64f64 = fpext <64 x half> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f32_v64f64 = fpext <64 x float> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f16_v64f32 = call <64 x float> @llvm.vp.fpext.v64f32.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f16_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f16(<64 x half> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f32_v64f64 = call <64 x double> @llvm.vp.fpext.v64f64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f16_v128f32 = fpext <128 x half> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f16_v128f64 = fpext <128 x half> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f32_v128f64 = fpext <128 x float> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f16_v128f32 = call <128 x float> @llvm.vp.fpext.v128f32.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f16_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f16(<128 x half> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f32_v128f64 = call <128 x double> @llvm.vp.fpext.v128f64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f16_nxv1f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f16_nxv1f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f16_nxv1f32 = call @llvm.vp.fpext.nxv1f32.nxv1f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f16_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1f64 = call @llvm.vp.fpext.nxv1f64.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f16_nxv2f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f16_nxv2f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f16_nxv2f32 = call @llvm.vp.fpext.nxv2f32.nxv2f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f16_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2f64 = call @llvm.vp.fpext.nxv2f64.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f16_nxv4f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f16_nxv4f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f16_nxv4f32 = call @llvm.vp.fpext.nxv4f32.nxv4f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f16_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4f64 = call @llvm.vp.fpext.nxv4f64.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f16_nxv8f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f16_nxv8f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f16_nxv8f32 = call @llvm.vp.fpext.nxv8f32.nxv8f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f16_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8f64 = call @llvm.vp.fpext.nxv8f64.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f16_nxv16f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f16_nxv16f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f16_nxv16f32 = call @llvm.vp.fpext.nxv16f32.nxv16f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f16_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16f64 = call @llvm.vp.fpext.nxv16f64.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f16_nxv32f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f16_nxv32f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f16_nxv32f32 = call @llvm.vp.fpext.nxv32f32.nxv32f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f16_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32f64 = call @llvm.vp.fpext.nxv32f64.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f16_nxv64f32 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f16_nxv64f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64f64 = fpext undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f16_nxv64f32 = call @llvm.vp.fpext.nxv64f32.nxv64f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f16_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64f64 = call @llvm.vp.fpext.nxv64f64.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f16_v2f32 = fpext <2 x half> undef to <2 x float> %v2f16_v2f64 = fpext <2 x half> undef to <2 x double> @@ -2224,92 +2312,179 @@ define void @fpext() { } define void @fptrunc() { -; CHECK-LABEL: 'fptrunc' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2f16 = fptrunc <2 x float> undef to <2 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2f16 = fptrunc <2 x double> undef to <2 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2f32 = fptrunc <2 x double> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2f32 = call <2 x float> @llvm.vp.fptrunc.v2f32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4f16 = fptrunc <4 x float> undef to <4 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4f16 = fptrunc <4 x double> undef to <4 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4f32 = fptrunc <4 x double> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4f32 = call <4 x float> @llvm.vp.fptrunc.v4f32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8f16 = fptrunc <8 x float> undef to <8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8f16 = fptrunc <8 x double> undef to <8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8f32 = fptrunc <8 x double> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8f32 = call <8 x float> @llvm.vp.fptrunc.v8f32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16f16 = fptrunc <16 x float> undef to <16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16f16 = fptrunc <16 x double> undef to <16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16f32 = fptrunc <16 x double> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16f32 = call <16 x float> @llvm.vp.fptrunc.v16f32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32f16 = fptrunc <32 x float> undef to <32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32f16 = fptrunc <32 x double> undef to <32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32f32 = fptrunc <32 x double> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32f32 = call <32 x float> @llvm.vp.fptrunc.v32f32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64f16 = fptrunc <64 x float> undef to <64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64f16 = fptrunc <64 x double> undef to <64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64f32 = fptrunc <64 x double> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64f32 = call <64 x float> @llvm.vp.fptrunc.v64f32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128f16 = fptrunc <128 x float> undef to <128 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128f16 = fptrunc <128 x double> undef to <128 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128f32 = fptrunc <128 x double> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128f32 = call <128 x float> @llvm.vp.fptrunc.v128f32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1f32 = call @llvm.vp.fptrunc.nxv1f32.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv1f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv1f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv1f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2f32 = call @llvm.vp.fptrunc.nxv2f32.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4f32 = call @llvm.vp.fptrunc.nxv4f32.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8f32 = call @llvm.vp.fptrunc.nxv8f32.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16f32 = call @llvm.vp.fptrunc.nxv16f32.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32f32 = call @llvm.vp.fptrunc.nxv32f32.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64f16 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64f32 = fptrunc undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64f32 = call @llvm.vp.fptrunc.nxv64f32.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'fptrunc' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2f16 = fptrunc <2 x float> undef to <2 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2f16 = fptrunc <2 x double> undef to <2 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2f32 = fptrunc <2 x double> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2f32 = call <2 x float> @llvm.vp.fptrunc.v2f32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4f16 = fptrunc <4 x float> undef to <4 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4f16 = fptrunc <4 x double> undef to <4 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4f32 = fptrunc <4 x double> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4f32 = call <4 x float> @llvm.vp.fptrunc.v4f32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8f16 = fptrunc <8 x float> undef to <8 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8f16 = fptrunc <8 x double> undef to <8 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8f32 = fptrunc <8 x double> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8f32 = call <8 x float> @llvm.vp.fptrunc.v8f32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16f16 = fptrunc <16 x float> undef to <16 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16f16 = fptrunc <16 x double> undef to <16 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16f32 = fptrunc <16 x double> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16f32 = call <16 x float> @llvm.vp.fptrunc.v16f32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32f16 = fptrunc <32 x float> undef to <32 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32f16 = fptrunc <32 x double> undef to <32 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32f32 = fptrunc <32 x double> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32f32 = call <32 x float> @llvm.vp.fptrunc.v32f32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64f16 = fptrunc <64 x float> undef to <64 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64f16 = fptrunc <64 x double> undef to <64 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64f32 = fptrunc <64 x double> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64f32 = call <64 x float> @llvm.vp.fptrunc.v64f32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128f16 = fptrunc <128 x float> undef to <128 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128f16 = fptrunc <128 x double> undef to <128 x half> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128f32 = fptrunc <128 x double> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128f32 = call <128 x float> @llvm.vp.fptrunc.v128f32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1f32 = call @llvm.vp.fptrunc.nxv1f32.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv1f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv1f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv1f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2f32 = call @llvm.vp.fptrunc.nxv2f32.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4f32 = call @llvm.vp.fptrunc.nxv4f32.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8f32 = call @llvm.vp.fptrunc.nxv8f32.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16f32 = call @llvm.vp.fptrunc.nxv16f32.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32f32 = call @llvm.vp.fptrunc.nxv32f32.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64f16 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64f32 = fptrunc undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64f32 = call @llvm.vp.fptrunc.nxv64f32.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'fptrunc' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2f16 = fptrunc <2 x float> undef to <2 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2f16 = fptrunc <2 x double> undef to <2 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2f32 = fptrunc <2 x double> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2f16 = call <2 x half> @llvm.vp.fptrunc.v2f16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2f32 = call <2 x float> @llvm.vp.fptrunc.v2f32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f32_v4f16 = fptrunc <4 x float> undef to <4 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f64_v4f16 = fptrunc <4 x double> undef to <4 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4f64_v4f32 = fptrunc <4 x double> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f32_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f64_v4f16 = call <4 x half> @llvm.vp.fptrunc.v4f16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4f64_v4f32 = call <4 x float> @llvm.vp.fptrunc.v4f32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f32_v8f16 = fptrunc <8 x float> undef to <8 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f64_v8f16 = fptrunc <8 x double> undef to <8 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8f64_v8f32 = fptrunc <8 x double> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f32_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f64_v8f16 = call <8 x half> @llvm.vp.fptrunc.v8f16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8f64_v8f32 = call <8 x float> @llvm.vp.fptrunc.v8f32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f32_v16f16 = fptrunc <16 x float> undef to <16 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f64_v16f16 = fptrunc <16 x double> undef to <16 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16f64_v16f32 = fptrunc <16 x double> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f32_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f64_v16f16 = call <16 x half> @llvm.vp.fptrunc.v16f16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16f64_v16f32 = call <16 x float> @llvm.vp.fptrunc.v16f32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f32_v32f16 = fptrunc <32 x float> undef to <32 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f64_v32f16 = fptrunc <32 x double> undef to <32 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v32f64_v32f32 = fptrunc <32 x double> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f32_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f64_v32f16 = call <32 x half> @llvm.vp.fptrunc.v32f16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v32f64_v32f32 = call <32 x float> @llvm.vp.fptrunc.v32f32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f32_v64f16 = fptrunc <64 x float> undef to <64 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f64_v64f16 = fptrunc <64 x double> undef to <64 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v64f64_v64f32 = fptrunc <64 x double> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f32_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f64_v64f16 = call <64 x half> @llvm.vp.fptrunc.v64f16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v64f64_v64f32 = call <64 x float> @llvm.vp.fptrunc.v64f32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f32_v128f16 = fptrunc <128 x float> undef to <128 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f64_v128f16 = fptrunc <128 x double> undef to <128 x half> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %v128f64_v128f32 = fptrunc <128 x double> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f32_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f64_v128f16 = call <128 x half> @llvm.vp.fptrunc.v128f16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 128 for instruction: %vp_v128f64_v128f32 = call <128 x float> @llvm.vp.fptrunc.v128f32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1f16 = call @llvm.vp.fptrunc.nxv1f16.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1f32 = call @llvm.vp.fptrunc.nxv1f32.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv1f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv1f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv1f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2f16 = call @llvm.vp.fptrunc.nxv2f16.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2f32 = call @llvm.vp.fptrunc.nxv2f32.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4f16 = call @llvm.vp.fptrunc.nxv4f16.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4f32 = call @llvm.vp.fptrunc.nxv4f32.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8f16 = call @llvm.vp.fptrunc.nxv8f16.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8f32 = call @llvm.vp.fptrunc.nxv8f32.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16f16 = call @llvm.vp.fptrunc.nxv16f16.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16f32 = call @llvm.vp.fptrunc.nxv16f32.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32f16 = call @llvm.vp.fptrunc.nxv32f16.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32f32 = call @llvm.vp.fptrunc.nxv32f32.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64f16 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64f32 = fptrunc undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64f16 = call @llvm.vp.fptrunc.nxv64f16.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64f32 = call @llvm.vp.fptrunc.nxv64f32.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f32_v2f16 = fptrunc <2 x float> undef to <2 x half> %v2f64_v2f16 = fptrunc <2 x double> undef to <2 x half> @@ -2427,288 +2602,571 @@ define void @fptrunc() { } define void @fptosi() { -; CHECK-LABEL: 'fptosi' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2i8 = fptosi <2 x float> undef to <2 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i8 = fptosi <2 x double> undef to <2 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i16 = fptosi <2 x float> undef to <2 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2i16 = fptosi <2 x double> undef to <2 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i32 = fptosi <2 x float> undef to <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i32 = fptosi <2 x double> undef to <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i64 = fptosi <2 x float> undef to <2 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i64 = fptosi <2 x double> undef to <2 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i1 = fptosi <2 x float> undef to <2 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i1 = fptosi <2 x double> undef to <2 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i8 = fptosi <4 x float> undef to <4 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i8 = fptosi <4 x double> undef to <4 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i16 = fptosi <4 x float> undef to <4 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i16 = fptosi <4 x double> undef to <4 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i32 = fptosi <4 x float> undef to <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4i32 = fptosi <4 x double> undef to <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i64 = fptosi <4 x float> undef to <4 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i64 = fptosi <4 x double> undef to <4 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f32_v4i1 = fptosi <4 x float> undef to <4 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i1 = fptosi <4 x double> undef to <4 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i8 = fptosi <8 x float> undef to <8 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i8 = fptosi <8 x double> undef to <8 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8i16 = fptosi <8 x float> undef to <8 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8i16 = fptosi <8 x double> undef to <8 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i32 = fptosi <8 x float> undef to <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8i32 = fptosi <8 x double> undef to <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8i64 = fptosi <8 x float> undef to <8 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i64 = fptosi <8 x double> undef to <8 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f32_v8i1 = fptosi <8 x float> undef to <8 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f64_v8i1 = fptosi <8 x double> undef to <8 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16f32_v16i8 = fptosi <16 x float> undef to <16 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16f64_v16i8 = fptosi <16 x double> undef to <16 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16i16 = fptosi <16 x float> undef to <16 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16i16 = fptosi <16 x double> undef to <16 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f32_v16i32 = fptosi <16 x float> undef to <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16i32 = fptosi <16 x double> undef to <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16i64 = fptosi <16 x float> undef to <16 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f64_v16i64 = fptosi <16 x double> undef to <16 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f32_v16i1 = fptosi <16 x float> undef to <16 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f64_v16i1 = fptosi <16 x double> undef to <16 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32f32_v32i8 = fptosi <32 x float> undef to <32 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v32f64_v32i8 = fptosi <32 x double> undef to <32 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32i16 = fptosi <32 x float> undef to <32 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32i16 = fptosi <32 x double> undef to <32 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f32_v32i32 = fptosi <32 x float> undef to <32 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32i32 = fptosi <32 x double> undef to <32 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32i64 = fptosi <32 x float> undef to <32 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32f64_v32i64 = fptosi <32 x double> undef to <32 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32f32_v32i1 = fptosi <32 x float> undef to <32 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f64_v32i1 = fptosi <32 x double> undef to <32 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64f32_v64i8 = fptosi <64 x float> undef to <64 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64f64_v64i8 = fptosi <64 x double> undef to <64 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64i16 = fptosi <64 x float> undef to <64 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64i16 = fptosi <64 x double> undef to <64 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64f32_v64i32 = fptosi <64 x float> undef to <64 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64i32 = fptosi <64 x double> undef to <64 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64i64 = fptosi <64 x float> undef to <64 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64f64_v64i64 = fptosi <64 x double> undef to <64 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64f32_v64i1 = fptosi <64 x float> undef to <64 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f64_v64i1 = fptosi <64 x double> undef to <64 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128f32_v128i8 = fptosi <128 x float> undef to <128 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128f64_v128i8 = fptosi <128 x double> undef to <128 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128i16 = fptosi <128 x float> undef to <128 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128i16 = fptosi <128 x double> undef to <128 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v128f32_v128i32 = fptosi <128 x float> undef to <128 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128i32 = fptosi <128 x double> undef to <128 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128i64 = fptosi <128 x float> undef to <128 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v128f64_v128i64 = fptosi <128 x double> undef to <128 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128f32_v128i1 = fptosi <128 x float> undef to <128 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128f64_v128i1 = fptosi <128 x double> undef to <128 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f32_nxv1i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f32_nxv1i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv2i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f32_nxv2i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f32_nxv4i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f64_nxv4i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8f32_nxv8i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8f64_nxv8i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f32_nxv8i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f64_nxv8i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f32_nxv8i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f64_nxv8i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16f32_nxv16i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16f64_nxv16i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f32_nxv16i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16f64_nxv16i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16f32_nxv16i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f64_nxv16i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32f32_nxv32i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32f64_nxv32i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32f32_nxv32i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32f64_nxv32i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32f32_nxv32i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f64_nxv32i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64f32_nxv64i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %nxv64f64_nxv64i8 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64i16 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64f32_nxv64i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64i32 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64f64_nxv64i64 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64f32_nxv64i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64f64_nxv64i1 = fptosi undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'fptosi' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2i8 = fptosi <2 x float> undef to <2 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i8 = fptosi <2 x double> undef to <2 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i16 = fptosi <2 x float> undef to <2 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2i16 = fptosi <2 x double> undef to <2 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i32 = fptosi <2 x float> undef to <2 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i32 = fptosi <2 x double> undef to <2 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i64 = fptosi <2 x float> undef to <2 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i64 = fptosi <2 x double> undef to <2 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i1 = fptosi <2 x float> undef to <2 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i1 = fptosi <2 x double> undef to <2 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i8 = fptosi <4 x float> undef to <4 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i8 = fptosi <4 x double> undef to <4 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i16 = fptosi <4 x float> undef to <4 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i16 = fptosi <4 x double> undef to <4 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i32 = fptosi <4 x float> undef to <4 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4i32 = fptosi <4 x double> undef to <4 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i64 = fptosi <4 x float> undef to <4 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i64 = fptosi <4 x double> undef to <4 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f32_v4i1 = fptosi <4 x float> undef to <4 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i1 = fptosi <4 x double> undef to <4 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i8 = fptosi <8 x float> undef to <8 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i8 = fptosi <8 x double> undef to <8 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8i16 = fptosi <8 x float> undef to <8 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8i16 = fptosi <8 x double> undef to <8 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i32 = fptosi <8 x float> undef to <8 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8i32 = fptosi <8 x double> undef to <8 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8i64 = fptosi <8 x float> undef to <8 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i64 = fptosi <8 x double> undef to <8 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f32_v8i1 = fptosi <8 x float> undef to <8 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f64_v8i1 = fptosi <8 x double> undef to <8 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16f32_v16i8 = fptosi <16 x float> undef to <16 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16f64_v16i8 = fptosi <16 x double> undef to <16 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16i16 = fptosi <16 x float> undef to <16 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16i16 = fptosi <16 x double> undef to <16 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f32_v16i32 = fptosi <16 x float> undef to <16 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16i32 = fptosi <16 x double> undef to <16 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16i64 = fptosi <16 x float> undef to <16 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f64_v16i64 = fptosi <16 x double> undef to <16 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f32_v16i1 = fptosi <16 x float> undef to <16 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f64_v16i1 = fptosi <16 x double> undef to <16 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32f32_v32i8 = fptosi <32 x float> undef to <32 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v32f64_v32i8 = fptosi <32 x double> undef to <32 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32i16 = fptosi <32 x float> undef to <32 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32i16 = fptosi <32 x double> undef to <32 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f32_v32i32 = fptosi <32 x float> undef to <32 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32i32 = fptosi <32 x double> undef to <32 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32i64 = fptosi <32 x float> undef to <32 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32f64_v32i64 = fptosi <32 x double> undef to <32 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32f32_v32i1 = fptosi <32 x float> undef to <32 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f64_v32i1 = fptosi <32 x double> undef to <32 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64f32_v64i8 = fptosi <64 x float> undef to <64 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64f64_v64i8 = fptosi <64 x double> undef to <64 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64i16 = fptosi <64 x float> undef to <64 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64i16 = fptosi <64 x double> undef to <64 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64f32_v64i32 = fptosi <64 x float> undef to <64 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64i32 = fptosi <64 x double> undef to <64 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64i64 = fptosi <64 x float> undef to <64 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64f64_v64i64 = fptosi <64 x double> undef to <64 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64f32_v64i1 = fptosi <64 x float> undef to <64 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f64_v64i1 = fptosi <64 x double> undef to <64 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128f32_v128i8 = fptosi <128 x float> undef to <128 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128f64_v128i8 = fptosi <128 x double> undef to <128 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128i16 = fptosi <128 x float> undef to <128 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128i16 = fptosi <128 x double> undef to <128 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v128f32_v128i32 = fptosi <128 x float> undef to <128 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128i32 = fptosi <128 x double> undef to <128 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128i64 = fptosi <128 x float> undef to <128 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v128f64_v128i64 = fptosi <128 x double> undef to <128 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128f32_v128i1 = fptosi <128 x float> undef to <128 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128f64_v128i1 = fptosi <128 x double> undef to <128 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f32_nxv1i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f32_nxv1i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv2i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f32_nxv2i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f32_nxv4i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f64_nxv4i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8f32_nxv8i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8f64_nxv8i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f32_nxv8i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f64_nxv8i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f32_nxv8i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f64_nxv8i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16f32_nxv16i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16f64_nxv16i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f32_nxv16i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16f64_nxv16i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16f32_nxv16i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f64_nxv16i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32f32_nxv32i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32f64_nxv32i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32f32_nxv32i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32f64_nxv32i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32f32_nxv32i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f64_nxv32i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64f32_nxv64i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %nxv64f64_nxv64i8 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64i16 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64f32_nxv64i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64i32 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64f64_nxv64i64 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64f32_nxv64i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64f64_nxv64i1 = fptosi undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'fptosi' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i8 = fptosi <2 x float> undef to <2 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i8 = fptosi <2 x double> undef to <2 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i16 = fptosi <2 x float> undef to <2 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i16 = fptosi <2 x double> undef to <2 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i32 = fptosi <2 x float> undef to <2 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i32 = fptosi <2 x double> undef to <2 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i64 = fptosi <2 x float> undef to <2 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i64 = fptosi <2 x double> undef to <2 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v2f32_v2i1 = fptosi <2 x float> undef to <2 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v2f64_v2i1 = fptosi <2 x double> undef to <2 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptosi.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptosi.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptosi.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptosi.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptosi.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i8 = fptosi <4 x float> undef to <4 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i8 = fptosi <4 x double> undef to <4 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i16 = fptosi <4 x float> undef to <4 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i16 = fptosi <4 x double> undef to <4 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i32 = fptosi <4 x float> undef to <4 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i32 = fptosi <4 x double> undef to <4 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4f32_v4i64 = fptosi <4 x float> undef to <4 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4f64_v4i64 = fptosi <4 x double> undef to <4 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %v4f32_v4i1 = fptosi <4 x float> undef to <4 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %v4f64_v4i1 = fptosi <4 x double> undef to <4 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptosi.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptosi.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptosi.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptosi.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptosi.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i8 = fptosi <8 x float> undef to <8 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i8 = fptosi <8 x double> undef to <8 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i16 = fptosi <8 x float> undef to <8 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i16 = fptosi <8 x double> undef to <8 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i32 = fptosi <8 x float> undef to <8 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i32 = fptosi <8 x double> undef to <8 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8f32_v8i64 = fptosi <8 x float> undef to <8 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8f64_v8i64 = fptosi <8 x double> undef to <8 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %v8f32_v8i1 = fptosi <8 x float> undef to <8 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %v8f64_v8i1 = fptosi <8 x double> undef to <8 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptosi.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptosi.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptosi.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptosi.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptosi.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i8 = fptosi <16 x float> undef to <16 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i8 = fptosi <16 x double> undef to <16 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i16 = fptosi <16 x float> undef to <16 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i16 = fptosi <16 x double> undef to <16 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i32 = fptosi <16 x float> undef to <16 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i32 = fptosi <16 x double> undef to <16 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16f32_v16i64 = fptosi <16 x float> undef to <16 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16f64_v16i64 = fptosi <16 x double> undef to <16 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %v16f32_v16i1 = fptosi <16 x float> undef to <16 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %v16f64_v16i1 = fptosi <16 x double> undef to <16 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptosi.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptosi.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptosi.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptosi.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptosi.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i8 = fptosi <32 x float> undef to <32 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i8 = fptosi <32 x double> undef to <32 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i16 = fptosi <32 x float> undef to <32 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i16 = fptosi <32 x double> undef to <32 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i32 = fptosi <32 x float> undef to <32 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i32 = fptosi <32 x double> undef to <32 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32f32_v32i64 = fptosi <32 x float> undef to <32 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32f64_v32i64 = fptosi <32 x double> undef to <32 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %v32f32_v32i1 = fptosi <32 x float> undef to <32 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %v32f64_v32i1 = fptosi <32 x double> undef to <32 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptosi.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptosi.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptosi.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptosi.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptosi.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f32_v64i8 = fptosi <64 x float> undef to <64 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f64_v64i8 = fptosi <64 x double> undef to <64 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f32_v64i16 = fptosi <64 x float> undef to <64 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f64_v64i16 = fptosi <64 x double> undef to <64 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v64f32_v64i32 = fptosi <64 x float> undef to <64 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v64f64_v64i32 = fptosi <64 x double> undef to <64 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64f32_v64i64 = fptosi <64 x float> undef to <64 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64f64_v64i64 = fptosi <64 x double> undef to <64 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %v64f32_v64i1 = fptosi <64 x float> undef to <64 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %v64f64_v64i1 = fptosi <64 x double> undef to <64 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptosi.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptosi.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptosi.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptosi.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptosi.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %v128f32_v128i8 = fptosi <128 x float> undef to <128 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %v128f64_v128i8 = fptosi <128 x double> undef to <128 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %v128f32_v128i16 = fptosi <128 x float> undef to <128 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %v128f64_v128i16 = fptosi <128 x double> undef to <128 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %v128f32_v128i32 = fptosi <128 x float> undef to <128 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %v128f64_v128i32 = fptosi <128 x double> undef to <128 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128f32_v128i64 = fptosi <128 x float> undef to <128 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128f64_v128i64 = fptosi <128 x double> undef to <128 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %v128f32_v128i1 = fptosi <128 x float> undef to <128 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %v128f64_v128i1 = fptosi <128 x double> undef to <128 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptosi.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptosi.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptosi.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptosi.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptosi.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptosi.nxv1i8.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptosi.nxv1i16.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptosi.nxv1i32.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptosi.nxv1i64.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptosi.nxv1i1.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptosi.nxv2i8.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptosi.nxv2i16.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptosi.nxv2i32.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptosi.nxv2i64.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptosi.nxv2i1.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptosi.nxv4i8.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptosi.nxv4i16.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptosi.nxv4i32.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptosi.nxv4i64.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptosi.nxv4i1.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptosi.nxv8i8.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptosi.nxv8i16.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptosi.nxv8i32.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptosi.nxv8i64.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptosi.nxv8i1.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptosi.nxv16i8.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptosi.nxv16i16.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptosi.nxv16i32.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptosi.nxv16i64.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptosi.nxv16i1.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptosi.nxv32i8.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptosi.nxv32i16.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptosi.nxv32i32.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptosi.nxv32i64.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptosi.nxv32i1.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i8 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i16 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i32 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i64 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i1 = fptosi undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptosi.nxv64i8.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptosi.nxv64i16.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptosi.nxv64i32.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptosi.nxv64i64.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptosi.nxv64i1.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f32_v2i8 = fptosi <2 x float> undef to <2 x i8> %v2f64_v2i8 = fptosi <2 x double> undef to <2 x i8> @@ -3022,288 +3480,571 @@ define void @fptosi() { } define void @fptoui() { -; CHECK-LABEL: 'fptoui' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2i8 = fptoui <2 x float> undef to <2 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i8 = fptoui <2 x double> undef to <2 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i16 = fptoui <2 x float> undef to <2 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2i16 = fptoui <2 x double> undef to <2 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i32 = fptoui <2 x float> undef to <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i32 = fptoui <2 x double> undef to <2 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i64 = fptoui <2 x float> undef to <2 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i64 = fptoui <2 x double> undef to <2 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i1 = fptoui <2 x float> undef to <2 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i1 = fptoui <2 x double> undef to <2 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i8 = fptoui <4 x float> undef to <4 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i8 = fptoui <4 x double> undef to <4 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i16 = fptoui <4 x float> undef to <4 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i16 = fptoui <4 x double> undef to <4 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i32 = fptoui <4 x float> undef to <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4i32 = fptoui <4 x double> undef to <4 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i64 = fptoui <4 x float> undef to <4 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i64 = fptoui <4 x double> undef to <4 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f32_v4i1 = fptoui <4 x float> undef to <4 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i1 = fptoui <4 x double> undef to <4 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i8 = fptoui <8 x float> undef to <8 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i8 = fptoui <8 x double> undef to <8 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8i16 = fptoui <8 x float> undef to <8 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8i16 = fptoui <8 x double> undef to <8 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i32 = fptoui <8 x float> undef to <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8i32 = fptoui <8 x double> undef to <8 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8i64 = fptoui <8 x float> undef to <8 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i64 = fptoui <8 x double> undef to <8 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f32_v8i1 = fptoui <8 x float> undef to <8 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f64_v8i1 = fptoui <8 x double> undef to <8 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16f32_v16i8 = fptoui <16 x float> undef to <16 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16f64_v16i8 = fptoui <16 x double> undef to <16 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16i16 = fptoui <16 x float> undef to <16 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16i16 = fptoui <16 x double> undef to <16 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f32_v16i32 = fptoui <16 x float> undef to <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16i32 = fptoui <16 x double> undef to <16 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16i64 = fptoui <16 x float> undef to <16 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f64_v16i64 = fptoui <16 x double> undef to <16 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f32_v16i1 = fptoui <16 x float> undef to <16 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f64_v16i1 = fptoui <16 x double> undef to <16 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32f32_v32i8 = fptoui <32 x float> undef to <32 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v32f64_v32i8 = fptoui <32 x double> undef to <32 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32i16 = fptoui <32 x float> undef to <32 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32i16 = fptoui <32 x double> undef to <32 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f32_v32i32 = fptoui <32 x float> undef to <32 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32i32 = fptoui <32 x double> undef to <32 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32i64 = fptoui <32 x float> undef to <32 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32f64_v32i64 = fptoui <32 x double> undef to <32 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32f32_v32i1 = fptoui <32 x float> undef to <32 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f64_v32i1 = fptoui <32 x double> undef to <32 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64f32_v64i8 = fptoui <64 x float> undef to <64 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64f64_v64i8 = fptoui <64 x double> undef to <64 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64i16 = fptoui <64 x float> undef to <64 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64i16 = fptoui <64 x double> undef to <64 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64f32_v64i32 = fptoui <64 x float> undef to <64 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64i32 = fptoui <64 x double> undef to <64 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64i64 = fptoui <64 x float> undef to <64 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64f64_v64i64 = fptoui <64 x double> undef to <64 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64f32_v64i1 = fptoui <64 x float> undef to <64 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f64_v64i1 = fptoui <64 x double> undef to <64 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128f32_v128i8 = fptoui <128 x float> undef to <128 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128f64_v128i8 = fptoui <128 x double> undef to <128 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128i16 = fptoui <128 x float> undef to <128 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128i16 = fptoui <128 x double> undef to <128 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v128f32_v128i32 = fptoui <128 x float> undef to <128 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128i32 = fptoui <128 x double> undef to <128 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128i64 = fptoui <128 x float> undef to <128 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v128f64_v128i64 = fptoui <128 x double> undef to <128 x i64> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128f32_v128i1 = fptoui <128 x float> undef to <128 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128f64_v128i1 = fptoui <128 x double> undef to <128 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f32_nxv1i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f32_nxv1i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv2i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f32_nxv2i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f32_nxv4i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f64_nxv4i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8f32_nxv8i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8f64_nxv8i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f32_nxv8i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f64_nxv8i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f32_nxv8i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f64_nxv8i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16f32_nxv16i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16f64_nxv16i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f32_nxv16i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16f64_nxv16i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16f32_nxv16i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f64_nxv16i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32f32_nxv32i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32f64_nxv32i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32f32_nxv32i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32f64_nxv32i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32f32_nxv32i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f64_nxv32i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64f32_nxv64i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %nxv64f64_nxv64i8 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64i16 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64f32_nxv64i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64i32 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64f64_nxv64i64 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64f32_nxv64i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64f64_nxv64i1 = fptoui undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'fptoui' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f32_v2i8 = fptoui <2 x float> undef to <2 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i8 = fptoui <2 x double> undef to <2 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i16 = fptoui <2 x float> undef to <2 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f64_v2i16 = fptoui <2 x double> undef to <2 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i32 = fptoui <2 x float> undef to <2 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i32 = fptoui <2 x double> undef to <2 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2i64 = fptoui <2 x float> undef to <2 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f64_v2i64 = fptoui <2 x double> undef to <2 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i1 = fptoui <2 x float> undef to <2 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i1 = fptoui <2 x double> undef to <2 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i8 = fptoui <4 x float> undef to <4 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i8 = fptoui <4 x double> undef to <4 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i16 = fptoui <4 x float> undef to <4 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i16 = fptoui <4 x double> undef to <4 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4i32 = fptoui <4 x float> undef to <4 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4i32 = fptoui <4 x double> undef to <4 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4i64 = fptoui <4 x float> undef to <4 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4i64 = fptoui <4 x double> undef to <4 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f32_v4i1 = fptoui <4 x float> undef to <4 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f64_v4i1 = fptoui <4 x double> undef to <4 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i8 = fptoui <8 x float> undef to <8 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i8 = fptoui <8 x double> undef to <8 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8i16 = fptoui <8 x float> undef to <8 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8i16 = fptoui <8 x double> undef to <8 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f32_v8i32 = fptoui <8 x float> undef to <8 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8i32 = fptoui <8 x double> undef to <8 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8i64 = fptoui <8 x float> undef to <8 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f64_v8i64 = fptoui <8 x double> undef to <8 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f32_v8i1 = fptoui <8 x float> undef to <8 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f64_v8i1 = fptoui <8 x double> undef to <8 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16f32_v16i8 = fptoui <16 x float> undef to <16 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16f64_v16i8 = fptoui <16 x double> undef to <16 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16i16 = fptoui <16 x float> undef to <16 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16i16 = fptoui <16 x double> undef to <16 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f32_v16i32 = fptoui <16 x float> undef to <16 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16i32 = fptoui <16 x double> undef to <16 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16i64 = fptoui <16 x float> undef to <16 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f64_v16i64 = fptoui <16 x double> undef to <16 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f32_v16i1 = fptoui <16 x float> undef to <16 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f64_v16i1 = fptoui <16 x double> undef to <16 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32f32_v32i8 = fptoui <32 x float> undef to <32 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v32f64_v32i8 = fptoui <32 x double> undef to <32 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32i16 = fptoui <32 x float> undef to <32 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32i16 = fptoui <32 x double> undef to <32 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f32_v32i32 = fptoui <32 x float> undef to <32 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32i32 = fptoui <32 x double> undef to <32 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32i64 = fptoui <32 x float> undef to <32 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32f64_v32i64 = fptoui <32 x double> undef to <32 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32f32_v32i1 = fptoui <32 x float> undef to <32 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f64_v32i1 = fptoui <32 x double> undef to <32 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64f32_v64i8 = fptoui <64 x float> undef to <64 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64f64_v64i8 = fptoui <64 x double> undef to <64 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64i16 = fptoui <64 x float> undef to <64 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64i16 = fptoui <64 x double> undef to <64 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64f32_v64i32 = fptoui <64 x float> undef to <64 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64i32 = fptoui <64 x double> undef to <64 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64i64 = fptoui <64 x float> undef to <64 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64f64_v64i64 = fptoui <64 x double> undef to <64 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64f32_v64i1 = fptoui <64 x float> undef to <64 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f64_v64i1 = fptoui <64 x double> undef to <64 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128f32_v128i8 = fptoui <128 x float> undef to <128 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128f64_v128i8 = fptoui <128 x double> undef to <128 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128i16 = fptoui <128 x float> undef to <128 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128i16 = fptoui <128 x double> undef to <128 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v128f32_v128i32 = fptoui <128 x float> undef to <128 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128i32 = fptoui <128 x double> undef to <128 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128i64 = fptoui <128 x float> undef to <128 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v128f64_v128i64 = fptoui <128 x double> undef to <128 x i64> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128f32_v128i1 = fptoui <128 x float> undef to <128 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128f64_v128i1 = fptoui <128 x double> undef to <128 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f32_nxv1i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f32_nxv1i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1f64_nxv1i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv2i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv2i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f32_nxv2i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f64_nxv2i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f32_nxv4i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f64_nxv4i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f32_nxv4i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f64_nxv4i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8f32_nxv8i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8f64_nxv8i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f32_nxv8i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f64_nxv8i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f32_nxv8i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f64_nxv8i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16f32_nxv16i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16f64_nxv16i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f32_nxv16i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16f64_nxv16i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16f32_nxv16i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f64_nxv16i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32f32_nxv32i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32f64_nxv32i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32f32_nxv32i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32f64_nxv32i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32f32_nxv32i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f64_nxv32i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64f32_nxv64i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %nxv64f64_nxv64i8 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64i16 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64f32_nxv64i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64i32 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64f64_nxv64i64 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64f32_nxv64i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64f64_nxv64i1 = fptoui undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'fptoui' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i8 = fptoui <2 x float> undef to <2 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i8 = fptoui <2 x double> undef to <2 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i16 = fptoui <2 x float> undef to <2 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i16 = fptoui <2 x double> undef to <2 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f32_v2i32 = fptoui <2 x float> undef to <2 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2f64_v2i32 = fptoui <2 x double> undef to <2 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f32_v2i64 = fptoui <2 x float> undef to <2 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2f64_v2i64 = fptoui <2 x double> undef to <2 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v2f32_v2i1 = fptoui <2 x float> undef to <2 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v2f64_v2i1 = fptoui <2 x double> undef to <2 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i8 = call <2 x i8> @llvm.vp.fptoui.v2i8.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i16 = call <2 x i16> @llvm.vp.fptoui.v2i16.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f32_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v2f64_v2i32 = call <2 x i32> @llvm.vp.fptoui.v2i32.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f32_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2f64_v2i64 = call <2 x i64> @llvm.vp.fptoui.v2i64.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %vp_v2f32_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f32(<2 x float> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %vp_v2f64_v2i1 = call <2 x i1> @llvm.vp.fptoui.v2i1.v2f64(<2 x double> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i8 = fptoui <4 x float> undef to <4 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i8 = fptoui <4 x double> undef to <4 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i16 = fptoui <4 x float> undef to <4 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i16 = fptoui <4 x double> undef to <4 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f32_v4i32 = fptoui <4 x float> undef to <4 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v4f64_v4i32 = fptoui <4 x double> undef to <4 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4f32_v4i64 = fptoui <4 x float> undef to <4 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4f64_v4i64 = fptoui <4 x double> undef to <4 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %v4f32_v4i1 = fptoui <4 x float> undef to <4 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %v4f64_v4i1 = fptoui <4 x double> undef to <4 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i8 = call <4 x i8> @llvm.vp.fptoui.v4i8.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i16 = call <4 x i16> @llvm.vp.fptoui.v4i16.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f32_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v4f64_v4i32 = call <4 x i32> @llvm.vp.fptoui.v4i32.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4f32_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4f64_v4i64 = call <4 x i64> @llvm.vp.fptoui.v4i64.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %vp_v4f32_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f32(<4 x float> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 39 for instruction: %vp_v4f64_v4i1 = call <4 x i1> @llvm.vp.fptoui.v4i1.v4f64(<4 x double> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i8 = fptoui <8 x float> undef to <8 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i8 = fptoui <8 x double> undef to <8 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i16 = fptoui <8 x float> undef to <8 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i16 = fptoui <8 x double> undef to <8 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f32_v8i32 = fptoui <8 x float> undef to <8 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v8f64_v8i32 = fptoui <8 x double> undef to <8 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8f32_v8i64 = fptoui <8 x float> undef to <8 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8f64_v8i64 = fptoui <8 x double> undef to <8 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %v8f32_v8i1 = fptoui <8 x float> undef to <8 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %v8f64_v8i1 = fptoui <8 x double> undef to <8 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i8 = call <8 x i8> @llvm.vp.fptoui.v8i8.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i16 = call <8 x i16> @llvm.vp.fptoui.v8i16.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f32_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v8f64_v8i32 = call <8 x i32> @llvm.vp.fptoui.v8i32.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8f32_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8f64_v8i64 = call <8 x i64> @llvm.vp.fptoui.v8i64.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %vp_v8f32_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f32(<8 x float> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 79 for instruction: %vp_v8f64_v8i1 = call <8 x i1> @llvm.vp.fptoui.v8i1.v8f64(<8 x double> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i8 = fptoui <16 x float> undef to <16 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i8 = fptoui <16 x double> undef to <16 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i16 = fptoui <16 x float> undef to <16 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i16 = fptoui <16 x double> undef to <16 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f32_v16i32 = fptoui <16 x float> undef to <16 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v16f64_v16i32 = fptoui <16 x double> undef to <16 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16f32_v16i64 = fptoui <16 x float> undef to <16 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16f64_v16i64 = fptoui <16 x double> undef to <16 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %v16f32_v16i1 = fptoui <16 x float> undef to <16 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %v16f64_v16i1 = fptoui <16 x double> undef to <16 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i8 = call <16 x i8> @llvm.vp.fptoui.v16i8.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i16 = call <16 x i16> @llvm.vp.fptoui.v16i16.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f32_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v16f64_v16i32 = call <16 x i32> @llvm.vp.fptoui.v16i32.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16f32_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16f64_v16i64 = call <16 x i64> @llvm.vp.fptoui.v16i64.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %vp_v16f32_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f32(<16 x float> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 159 for instruction: %vp_v16f64_v16i1 = call <16 x i1> @llvm.vp.fptoui.v16i1.v16f64(<16 x double> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i8 = fptoui <32 x float> undef to <32 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i8 = fptoui <32 x double> undef to <32 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i16 = fptoui <32 x float> undef to <32 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i16 = fptoui <32 x double> undef to <32 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f32_v32i32 = fptoui <32 x float> undef to <32 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v32f64_v32i32 = fptoui <32 x double> undef to <32 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32f32_v32i64 = fptoui <32 x float> undef to <32 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32f64_v32i64 = fptoui <32 x double> undef to <32 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %v32f32_v32i1 = fptoui <32 x float> undef to <32 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %v32f64_v32i1 = fptoui <32 x double> undef to <32 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i8 = call <32 x i8> @llvm.vp.fptoui.v32i8.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i16 = call <32 x i16> @llvm.vp.fptoui.v32i16.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f32_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v32f64_v32i32 = call <32 x i32> @llvm.vp.fptoui.v32i32.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32f32_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32f64_v32i64 = call <32 x i64> @llvm.vp.fptoui.v32i64.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %vp_v32f32_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f32(<32 x float> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 319 for instruction: %vp_v32f64_v32i1 = call <32 x i1> @llvm.vp.fptoui.v32i1.v32f64(<32 x double> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f32_v64i8 = fptoui <64 x float> undef to <64 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f64_v64i8 = fptoui <64 x double> undef to <64 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f32_v64i16 = fptoui <64 x float> undef to <64 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v64f64_v64i16 = fptoui <64 x double> undef to <64 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v64f32_v64i32 = fptoui <64 x float> undef to <64 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v64f64_v64i32 = fptoui <64 x double> undef to <64 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64f32_v64i64 = fptoui <64 x float> undef to <64 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64f64_v64i64 = fptoui <64 x double> undef to <64 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %v64f32_v64i1 = fptoui <64 x float> undef to <64 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %v64f64_v64i1 = fptoui <64 x double> undef to <64 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f32_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f64_v64i8 = call <64 x i8> @llvm.vp.fptoui.v64i8.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f32_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v64f64_v64i16 = call <64 x i16> @llvm.vp.fptoui.v64i16.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v64f32_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v64f64_v64i32 = call <64 x i32> @llvm.vp.fptoui.v64i32.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64f32_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64f64_v64i64 = call <64 x i64> @llvm.vp.fptoui.v64i64.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %vp_v64f32_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f32(<64 x float> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 639 for instruction: %vp_v64f64_v64i1 = call <64 x i1> @llvm.vp.fptoui.v64i1.v64f64(<64 x double> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %v128f32_v128i8 = fptoui <128 x float> undef to <128 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %v128f64_v128i8 = fptoui <128 x double> undef to <128 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %v128f32_v128i16 = fptoui <128 x float> undef to <128 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %v128f64_v128i16 = fptoui <128 x double> undef to <128 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %v128f32_v128i32 = fptoui <128 x float> undef to <128 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %v128f64_v128i32 = fptoui <128 x double> undef to <128 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128f32_v128i64 = fptoui <128 x float> undef to <128 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128f64_v128i64 = fptoui <128 x double> undef to <128 x i64> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %v128f32_v128i1 = fptoui <128 x float> undef to <128 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %v128f64_v128i1 = fptoui <128 x double> undef to <128 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %vp_v128f32_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 511 for instruction: %vp_v128f64_v128i8 = call <128 x i8> @llvm.vp.fptoui.v128i8.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %vp_v128f32_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 510 for instruction: %vp_v128f64_v128i16 = call <128 x i16> @llvm.vp.fptoui.v128i16.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %vp_v128f32_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 508 for instruction: %vp_v128f64_v128i32 = call <128 x i32> @llvm.vp.fptoui.v128i32.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128f32_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128f64_v128i64 = call <128 x i64> @llvm.vp.fptoui.v128i64.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %vp_v128f32_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f32(<128 x float> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1279 for instruction: %vp_v128f64_v128i1 = call <128 x i1> @llvm.vp.fptoui.v128i1.v128f64(<128 x double> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f32_nxv1i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1f64_nxv1i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i8 = call @llvm.vp.fptoui.nxv1i8.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i16 = call @llvm.vp.fptoui.nxv1i16.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i32 = call @llvm.vp.fptoui.nxv1i32.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i64 = call @llvm.vp.fptoui.nxv1i64.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f32_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1f64_nxv1i1 = call @llvm.vp.fptoui.nxv1i1.nxv1f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f32_nxv2i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2f64_nxv2i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i8 = call @llvm.vp.fptoui.nxv2i8.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i16 = call @llvm.vp.fptoui.nxv2i16.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i32 = call @llvm.vp.fptoui.nxv2i32.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i64 = call @llvm.vp.fptoui.nxv2i64.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f32_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2f64_nxv2i1 = call @llvm.vp.fptoui.nxv2i1.nxv2f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f32_nxv4i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4f64_nxv4i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i8 = call @llvm.vp.fptoui.nxv4i8.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i16 = call @llvm.vp.fptoui.nxv4i16.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i32 = call @llvm.vp.fptoui.nxv4i32.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i64 = call @llvm.vp.fptoui.nxv4i64.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f32_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4f64_nxv4i1 = call @llvm.vp.fptoui.nxv4i1.nxv4f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f32_nxv8i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8f64_nxv8i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i8 = call @llvm.vp.fptoui.nxv8i8.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i16 = call @llvm.vp.fptoui.nxv8i16.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i32 = call @llvm.vp.fptoui.nxv8i32.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i64 = call @llvm.vp.fptoui.nxv8i64.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f32_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8f64_nxv8i1 = call @llvm.vp.fptoui.nxv8i1.nxv8f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f32_nxv16i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16f64_nxv16i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i8 = call @llvm.vp.fptoui.nxv16i8.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i16 = call @llvm.vp.fptoui.nxv16i16.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i32 = call @llvm.vp.fptoui.nxv16i32.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i64 = call @llvm.vp.fptoui.nxv16i64.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f32_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16f64_nxv16i1 = call @llvm.vp.fptoui.nxv16i1.nxv16f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f32_nxv32i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32f64_nxv32i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i8 = call @llvm.vp.fptoui.nxv32i8.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i16 = call @llvm.vp.fptoui.nxv32i16.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i32 = call @llvm.vp.fptoui.nxv32i32.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i64 = call @llvm.vp.fptoui.nxv32i64.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f32_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32f64_nxv32i1 = call @llvm.vp.fptoui.nxv32i1.nxv32f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i8 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i16 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i32 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i64 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f32_nxv64i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64f64_nxv64i1 = fptoui undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i8 = call @llvm.vp.fptoui.nxv64i8.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i16 = call @llvm.vp.fptoui.nxv64i16.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i32 = call @llvm.vp.fptoui.nxv64i32.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i64 = call @llvm.vp.fptoui.nxv64i64.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f32_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64f64_nxv64i1 = call @llvm.vp.fptoui.nxv64i1.nxv64f64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f32_v2i8 = fptoui <2 x float> undef to <2 x i8> %v2f64_v2i8 = fptoui <2 x double> undef to <2 x i8> @@ -3617,288 +4358,571 @@ define void @fptoui() { } define void @sitofp() { -; CHECK-LABEL: 'sitofp' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f32 = sitofp <2 x i8> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f64 = sitofp <2 x i8> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16_v2f32 = sitofp <2 x i16> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_v2f64 = sitofp <2 x i16> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f32 = sitofp <2 x i32> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f64 = sitofp <2 x i32> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f32 = sitofp <2 x i64> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f64 = sitofp <2 x i64> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = sitofp <2 x i1> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = sitofp <2 x i1> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4f32 = sitofp <4 x i8> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_v4f64 = sitofp <4 x i8> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4f32 = sitofp <4 x i16> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16_v4f64 = sitofp <4 x i16> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4f32 = sitofp <4 x i32> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4f64 = sitofp <4 x i32> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i64_v4f32 = sitofp <4 x i64> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4f64 = sitofp <4 x i64> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_v4f32 = sitofp <4 x i1> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4f64 = sitofp <4 x i1> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_v8f32 = sitofp <8 x i8> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i8_v8f64 = sitofp <8 x i8> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8f32 = sitofp <8 x i16> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i16_v8f64 = sitofp <8 x i16> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8f32 = sitofp <8 x i32> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8f64 = sitofp <8 x i32> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8f32 = sitofp <8 x i64> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8f64 = sitofp <8 x i64> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8f32 = sitofp <8 x i1> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8f64 = sitofp <8 x i1> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i8_v16f32 = sitofp <16 x i8> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i8_v16f64 = sitofp <16 x i8> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16f32 = sitofp <16 x i16> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i16_v16f64 = sitofp <16 x i16> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_v16f32 = sitofp <16 x i32> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16f64 = sitofp <16 x i32> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i64_v16f32 = sitofp <16 x i64> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i64_v16f64 = sitofp <16 x i64> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16f32 = sitofp <16 x i1> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16f64 = sitofp <16 x i1> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i8_v32f32 = sitofp <32 x i8> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i8_v32f64 = sitofp <32 x i8> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32f32 = sitofp <32 x i16> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i16_v32f64 = sitofp <32 x i16> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32f32 = sitofp <32 x i32> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32f64 = sitofp <32 x i32> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i64_v32f32 = sitofp <32 x i64> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32f64 = sitofp <32 x i64> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32f32 = sitofp <32 x i1> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32f64 = sitofp <32 x i1> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64i8_v64f32 = sitofp <64 x i8> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i8_v64f64 = sitofp <64 x i8> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64f32 = sitofp <64 x i16> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i16_v64f64 = sitofp <64 x i16> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i32_v64f32 = sitofp <64 x i32> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64f64 = sitofp <64 x i32> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64f32 = sitofp <64 x i64> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v64i64_v64f64 = sitofp <64 x i64> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64f32 = sitofp <64 x i1> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64f64 = sitofp <64 x i1> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128i8_v128f32 = sitofp <128 x i8> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128i8_v128f64 = sitofp <128 x i8> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128f32 = sitofp <128 x i16> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128i16_v128f64 = sitofp <128 x i16> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v128i32_v128f32 = sitofp <128 x i32> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128f64 = sitofp <128 x i32> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128f32 = sitofp <128 x i64> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v128i64_v128f64 = sitofp <128 x i64> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128f32 = sitofp <128 x i1> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128f64 = sitofp <128 x i1> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i16_nxv1f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i8_nxv2f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i16_nxv2f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i64_nxv2f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_nxv2f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i8_nxv4f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i8_nxv4f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i16_nxv4f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i8_nxv8f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i8_nxv8f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i16_nxv8f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i32_nxv8f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i64_nxv8f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16i8_nxv16f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i8_nxv16f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i16_nxv16f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i32_nxv16f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i64_nxv16f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32i8_nxv32f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i8_nxv32f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i16_nxv32f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i32_nxv32f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i64_nxv32f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64i8_nxv64f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64i8_nxv64f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64i16_nxv64f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64i32_nxv64f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64i64_nxv64f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64i64_nxv64f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64f32 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64f64 = sitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'sitofp' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f32 = sitofp <2 x i8> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f64 = sitofp <2 x i8> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16_v2f32 = sitofp <2 x i16> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_v2f64 = sitofp <2 x i16> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f32 = sitofp <2 x i32> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f64 = sitofp <2 x i32> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f32 = sitofp <2 x i64> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f64 = sitofp <2 x i64> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = sitofp <2 x i1> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = sitofp <2 x i1> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4f32 = sitofp <4 x i8> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_v4f64 = sitofp <4 x i8> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4f32 = sitofp <4 x i16> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16_v4f64 = sitofp <4 x i16> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4f32 = sitofp <4 x i32> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4f64 = sitofp <4 x i32> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i64_v4f32 = sitofp <4 x i64> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4f64 = sitofp <4 x i64> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_v4f32 = sitofp <4 x i1> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4f64 = sitofp <4 x i1> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_v8f32 = sitofp <8 x i8> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i8_v8f64 = sitofp <8 x i8> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8f32 = sitofp <8 x i16> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i16_v8f64 = sitofp <8 x i16> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8f32 = sitofp <8 x i32> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8f64 = sitofp <8 x i32> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8f32 = sitofp <8 x i64> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8f64 = sitofp <8 x i64> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8f32 = sitofp <8 x i1> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8f64 = sitofp <8 x i1> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i8_v16f32 = sitofp <16 x i8> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i8_v16f64 = sitofp <16 x i8> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16f32 = sitofp <16 x i16> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i16_v16f64 = sitofp <16 x i16> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_v16f32 = sitofp <16 x i32> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16f64 = sitofp <16 x i32> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i64_v16f32 = sitofp <16 x i64> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i64_v16f64 = sitofp <16 x i64> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16f32 = sitofp <16 x i1> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16f64 = sitofp <16 x i1> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i8_v32f32 = sitofp <32 x i8> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i8_v32f64 = sitofp <32 x i8> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32f32 = sitofp <32 x i16> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i16_v32f64 = sitofp <32 x i16> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32f32 = sitofp <32 x i32> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32f64 = sitofp <32 x i32> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i64_v32f32 = sitofp <32 x i64> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32f64 = sitofp <32 x i64> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32f32 = sitofp <32 x i1> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32f64 = sitofp <32 x i1> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64i8_v64f32 = sitofp <64 x i8> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i8_v64f64 = sitofp <64 x i8> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64f32 = sitofp <64 x i16> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i16_v64f64 = sitofp <64 x i16> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i32_v64f32 = sitofp <64 x i32> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64f64 = sitofp <64 x i32> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64f32 = sitofp <64 x i64> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v64i64_v64f64 = sitofp <64 x i64> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64f32 = sitofp <64 x i1> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64f64 = sitofp <64 x i1> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128i8_v128f32 = sitofp <128 x i8> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128i8_v128f64 = sitofp <128 x i8> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128f32 = sitofp <128 x i16> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128i16_v128f64 = sitofp <128 x i16> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v128i32_v128f32 = sitofp <128 x i32> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128f64 = sitofp <128 x i32> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128f32 = sitofp <128 x i64> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v128i64_v128f64 = sitofp <128 x i64> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128f32 = sitofp <128 x i1> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128f64 = sitofp <128 x i1> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i16_nxv1f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i8_nxv2f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i16_nxv2f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i64_nxv2f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_nxv2f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i8_nxv4f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i8_nxv4f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i16_nxv4f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i8_nxv8f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i8_nxv8f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i16_nxv8f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i32_nxv8f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i64_nxv8f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16i8_nxv16f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i8_nxv16f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i16_nxv16f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i32_nxv16f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i64_nxv16f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32i8_nxv32f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i8_nxv32f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i16_nxv32f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i32_nxv32f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i64_nxv32f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64i8_nxv64f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64i8_nxv64f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64i16_nxv64f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64i32_nxv64f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64i64_nxv64f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64i64_nxv64f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64f32 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64f64 = sitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'sitofp' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_v2f32 = sitofp <2 x i8> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_v2f64 = sitofp <2 x i8> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i16_v2f32 = sitofp <2 x i16> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i16_v2f64 = sitofp <2 x i16> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i32_v2f32 = sitofp <2 x i32> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i32_v2f64 = sitofp <2 x i32> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i64_v2f32 = sitofp <2 x i64> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i64_v2f64 = sitofp <2 x i64> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = sitofp <2 x i1> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = sitofp <2 x i1> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.sitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.sitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i8_v4f32 = sitofp <4 x i8> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i8_v4f64 = sitofp <4 x i8> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i16_v4f32 = sitofp <4 x i16> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i16_v4f64 = sitofp <4 x i16> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i32_v4f32 = sitofp <4 x i32> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i32_v4f64 = sitofp <4 x i32> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i64_v4f32 = sitofp <4 x i64> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i64_v4f64 = sitofp <4 x i64> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_v4f32 = sitofp <4 x i1> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_v4f64 = sitofp <4 x i1> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.sitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.sitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i8_v8f32 = sitofp <8 x i8> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i8_v8f64 = sitofp <8 x i8> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i16_v8f32 = sitofp <8 x i16> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i16_v8f64 = sitofp <8 x i16> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i32_v8f32 = sitofp <8 x i32> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i32_v8f64 = sitofp <8 x i32> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i64_v8f32 = sitofp <8 x i64> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i64_v8f64 = sitofp <8 x i64> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i1_v8f32 = sitofp <8 x i1> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i1_v8f64 = sitofp <8 x i1> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.sitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.sitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i8_v16f32 = sitofp <16 x i8> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i8_v16f64 = sitofp <16 x i8> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i16_v16f32 = sitofp <16 x i16> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i16_v16f64 = sitofp <16 x i16> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i32_v16f32 = sitofp <16 x i32> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i32_v16f64 = sitofp <16 x i32> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i64_v16f32 = sitofp <16 x i64> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i64_v16f64 = sitofp <16 x i64> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i1_v16f32 = sitofp <16 x i1> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i1_v16f64 = sitofp <16 x i1> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.sitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.sitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i8_v32f32 = sitofp <32 x i8> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i8_v32f64 = sitofp <32 x i8> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i16_v32f32 = sitofp <32 x i16> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i16_v32f64 = sitofp <32 x i16> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i32_v32f32 = sitofp <32 x i32> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i32_v32f64 = sitofp <32 x i32> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32i64_v32f32 = sitofp <32 x i64> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32i64_v32f64 = sitofp <32 x i64> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i1_v32f32 = sitofp <32 x i1> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i1_v32f64 = sitofp <32 x i1> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.sitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.sitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i8_v64f32 = sitofp <64 x i8> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i8_v64f64 = sitofp <64 x i8> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i16_v64f32 = sitofp <64 x i16> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i16_v64f64 = sitofp <64 x i16> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v64i32_v64f32 = sitofp <64 x i32> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v64i32_v64f64 = sitofp <64 x i32> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64i64_v64f32 = sitofp <64 x i64> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64i64_v64f64 = sitofp <64 x i64> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i1_v64f32 = sitofp <64 x i1> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i1_v64f64 = sitofp <64 x i1> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.sitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.sitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i8_v128f32 = sitofp <128 x i8> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i8_v128f64 = sitofp <128 x i8> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v128i16_v128f32 = sitofp <128 x i16> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v128i16_v128f64 = sitofp <128 x i16> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %v128i32_v128f32 = sitofp <128 x i32> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %v128i32_v128f64 = sitofp <128 x i32> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128i64_v128f32 = sitofp <128 x i64> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128i64_v128f64 = sitofp <128 x i64> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i1_v128f32 = sitofp <128 x i1> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i1_v128f64 = sitofp <128 x i1> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.sitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.sitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i8_nxv1f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i8_nxv1f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i16_nxv1f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i16_nxv1f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i32_nxv1f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i32_nxv1f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i64_nxv1f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i64_nxv1f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i1_nxv1f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i1_nxv1f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i8_nxv2f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i8_nxv2f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i16_nxv2f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i16_nxv2f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i32_nxv2f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i32_nxv2f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i64_nxv2f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i64_nxv2f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i1_nxv2f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i1_nxv2f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.sitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.sitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i8_nxv4f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i8_nxv4f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i16_nxv4f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i16_nxv4f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i32_nxv4f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i32_nxv4f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i64_nxv4f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i64_nxv4f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i1_nxv4f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i1_nxv4f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.sitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.sitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i8_nxv8f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i8_nxv8f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i16_nxv8f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i16_nxv8f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i32_nxv8f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i32_nxv8f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i64_nxv8f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i64_nxv8f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i1_nxv8f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i1_nxv8f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.sitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.sitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i8_nxv16f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i8_nxv16f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i16_nxv16f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i16_nxv16f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i32_nxv16f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i32_nxv16f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i64_nxv16f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i64_nxv16f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i1_nxv16f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i1_nxv16f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.sitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.sitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i8_nxv32f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i8_nxv32f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i16_nxv32f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i16_nxv32f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i32_nxv32f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i32_nxv32f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i64_nxv32f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i64_nxv32f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i1_nxv32f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i1_nxv32f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.sitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.sitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i16_nxv64f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i16_nxv64f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i32_nxv64f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i32_nxv64f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64f32 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64f64 = sitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.sitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.sitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2i8_v2f32 = sitofp <2 x i8> undef to <2 x float> %v2i8_v2f64 = sitofp <2 x i8> undef to <2 x double> @@ -4212,288 +5236,571 @@ define void @sitofp() { } define void @uitofp() { -; CHECK-LABEL: 'uitofp' -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f32 = uitofp <2 x i8> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f64 = uitofp <2 x i8> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16_v2f32 = uitofp <2 x i16> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_v2f64 = uitofp <2 x i16> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f32 = uitofp <2 x i32> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f64 = uitofp <2 x i32> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f32 = uitofp <2 x i64> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f64 = uitofp <2 x i64> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = uitofp <2 x i1> undef to <2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = uitofp <2 x i1> undef to <2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4f32 = uitofp <4 x i8> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_v4f64 = uitofp <4 x i8> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4f32 = uitofp <4 x i16> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16_v4f64 = uitofp <4 x i16> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4f32 = uitofp <4 x i32> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4f64 = uitofp <4 x i32> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i64_v4f32 = uitofp <4 x i64> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4f64 = uitofp <4 x i64> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_v4f32 = uitofp <4 x i1> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4f64 = uitofp <4 x i1> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_v8f32 = uitofp <8 x i8> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i8_v8f64 = uitofp <8 x i8> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8f32 = uitofp <8 x i16> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i16_v8f64 = uitofp <8 x i16> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8f32 = uitofp <8 x i32> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8f64 = uitofp <8 x i32> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8f32 = uitofp <8 x i64> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8f64 = uitofp <8 x i64> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8f32 = uitofp <8 x i1> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8f64 = uitofp <8 x i1> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i8_v16f32 = uitofp <16 x i8> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i8_v16f64 = uitofp <16 x i8> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16f32 = uitofp <16 x i16> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i16_v16f64 = uitofp <16 x i16> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_v16f32 = uitofp <16 x i32> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16f64 = uitofp <16 x i32> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i64_v16f32 = uitofp <16 x i64> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i64_v16f64 = uitofp <16 x i64> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16f32 = uitofp <16 x i1> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16f64 = uitofp <16 x i1> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i8_v32f32 = uitofp <32 x i8> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i8_v32f64 = uitofp <32 x i8> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32f32 = uitofp <32 x i16> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i16_v32f64 = uitofp <32 x i16> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32f32 = uitofp <32 x i32> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32f64 = uitofp <32 x i32> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i64_v32f32 = uitofp <32 x i64> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32f64 = uitofp <32 x i64> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32f32 = uitofp <32 x i1> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32f64 = uitofp <32 x i1> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64i8_v64f32 = uitofp <64 x i8> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i8_v64f64 = uitofp <64 x i8> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64f32 = uitofp <64 x i16> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i16_v64f64 = uitofp <64 x i16> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i32_v64f32 = uitofp <64 x i32> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64f64 = uitofp <64 x i32> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64f32 = uitofp <64 x i64> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v64i64_v64f64 = uitofp <64 x i64> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64f32 = uitofp <64 x i1> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64f64 = uitofp <64 x i1> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128i8_v128f32 = uitofp <128 x i8> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128i8_v128f64 = uitofp <128 x i8> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128f32 = uitofp <128 x i16> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128i16_v128f64 = uitofp <128 x i16> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v128i32_v128f32 = uitofp <128 x i32> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128f64 = uitofp <128 x i32> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128f32 = uitofp <128 x i64> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v128i64_v128f64 = uitofp <128 x i64> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128f32 = uitofp <128 x i1> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128f64 = uitofp <128 x i1> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i16_nxv1f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i8_nxv2f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i16_nxv2f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i64_nxv2f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_nxv2f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i8_nxv4f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i8_nxv4f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i16_nxv4f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i8_nxv8f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i8_nxv8f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i16_nxv8f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i32_nxv8f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i64_nxv8f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16i8_nxv16f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i8_nxv16f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i16_nxv16f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i32_nxv16f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i64_nxv16f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32i8_nxv32f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i8_nxv32f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i16_nxv32f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i32_nxv32f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i64_nxv32f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64i8_nxv64f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64i8_nxv64f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64i16_nxv64f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64i32_nxv64f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64i64_nxv64f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64i64_nxv64f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64f32 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64f64 = uitofp undef to -; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'uitofp' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f32 = uitofp <2 x i8> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_v2f64 = uitofp <2 x i8> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i16_v2f32 = uitofp <2 x i16> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i16_v2f64 = uitofp <2 x i16> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f32 = uitofp <2 x i32> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i32_v2f64 = uitofp <2 x i32> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f32 = uitofp <2 x i64> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i64_v2f64 = uitofp <2 x i64> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = uitofp <2 x i1> undef to <2 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = uitofp <2 x i1> undef to <2 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4f32 = uitofp <4 x i8> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_v4f64 = uitofp <4 x i8> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4f32 = uitofp <4 x i16> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i16_v4f64 = uitofp <4 x i16> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4f32 = uitofp <4 x i32> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4f64 = uitofp <4 x i32> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i64_v4f32 = uitofp <4 x i64> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4f64 = uitofp <4 x i64> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_v4f32 = uitofp <4 x i1> undef to <4 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4f64 = uitofp <4 x i1> undef to <4 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_v8f32 = uitofp <8 x i8> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i8_v8f64 = uitofp <8 x i8> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8f32 = uitofp <8 x i16> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i16_v8f64 = uitofp <8 x i16> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8f32 = uitofp <8 x i32> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8f64 = uitofp <8 x i32> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8f32 = uitofp <8 x i64> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8f64 = uitofp <8 x i64> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8f32 = uitofp <8 x i1> undef to <8 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8f64 = uitofp <8 x i1> undef to <8 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i8_v16f32 = uitofp <16 x i8> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i8_v16f64 = uitofp <16 x i8> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16f32 = uitofp <16 x i16> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16i16_v16f64 = uitofp <16 x i16> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i32_v16f32 = uitofp <16 x i32> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16f64 = uitofp <16 x i32> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i64_v16f32 = uitofp <16 x i64> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i64_v16f64 = uitofp <16 x i64> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16f32 = uitofp <16 x i1> undef to <16 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16f64 = uitofp <16 x i1> undef to <16 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v32i8_v32f32 = uitofp <32 x i8> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i8_v32f64 = uitofp <32 x i8> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32f32 = uitofp <32 x i16> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32i16_v32f64 = uitofp <32 x i16> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32f32 = uitofp <32 x i32> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32f64 = uitofp <32 x i32> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i64_v32f32 = uitofp <32 x i64> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32f64 = uitofp <32 x i64> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32f32 = uitofp <32 x i1> undef to <32 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32f64 = uitofp <32 x i1> undef to <32 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v64i8_v64f32 = uitofp <64 x i8> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i8_v64f64 = uitofp <64 x i8> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64f32 = uitofp <64 x i16> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64i16_v64f64 = uitofp <64 x i16> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i32_v64f32 = uitofp <64 x i32> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64f64 = uitofp <64 x i32> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64f32 = uitofp <64 x i64> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v64i64_v64f64 = uitofp <64 x i64> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64f32 = uitofp <64 x i1> undef to <64 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64f64 = uitofp <64 x i1> undef to <64 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v128i8_v128f32 = uitofp <128 x i8> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %v128i8_v128f64 = uitofp <128 x i8> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128f32 = uitofp <128 x i16> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128i16_v128f64 = uitofp <128 x i16> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v128i32_v128f32 = uitofp <128 x i32> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128f64 = uitofp <128 x i32> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128f32 = uitofp <128 x i64> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %v128i64_v128f64 = uitofp <128 x i64> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128f32 = uitofp <128 x i1> undef to <128 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128f64 = uitofp <128 x i1> undef to <128 x double> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 64 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i8_nxv1f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i16_nxv1f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i32_nxv1f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i64_nxv1f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv1i1_nxv1f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i8_nxv2f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i16_nxv2f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i64_nxv2f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_nxv2f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i8_nxv4f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i8_nxv4f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i16_nxv4f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i8_nxv8f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i8_nxv8f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8i16_nxv8f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i32_nxv8f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i64_nxv8f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv16i8_nxv16f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i8_nxv16f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16i16_nxv16f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i32_nxv16f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i64_nxv16f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv32i8_nxv32f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i8_nxv32f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32i16_nxv32f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i32_nxv32f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i64_nxv32f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv64i8_nxv64f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %nxv64i8_nxv64f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64i16_nxv64f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv64i32_nxv64f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64i64_nxv64f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv64i64_nxv64f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64f32 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64f64 = uitofp undef to +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 103 for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'uitofp' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_v2f32 = uitofp <2 x i8> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_v2f64 = uitofp <2 x i8> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i16_v2f32 = uitofp <2 x i16> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i16_v2f64 = uitofp <2 x i16> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i32_v2f32 = uitofp <2 x i32> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i32_v2f64 = uitofp <2 x i32> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i64_v2f32 = uitofp <2 x i64> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i64_v2f64 = uitofp <2 x i64> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f32 = uitofp <2 x i1> undef to <2 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_v2f64 = uitofp <2 x i1> undef to <2 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi8_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi8_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i8(<2 x i8> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi16_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi16_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i16(<2 x i16> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi32_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi32_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i32(<2 x i32> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi64_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi64_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i64(<2 x i64> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f32 = call <2 x float> @llvm.vp.uitofp.v2f32.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %vp_v2fi1_v2f64 = call <2 x double> @llvm.vp.uitofp.v2f64.v2i1(<2 x i1> undef, <2 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i8_v4f32 = uitofp <4 x i8> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i8_v4f64 = uitofp <4 x i8> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i16_v4f32 = uitofp <4 x i16> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i16_v4f64 = uitofp <4 x i16> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i32_v4f32 = uitofp <4 x i32> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i32_v4f64 = uitofp <4 x i32> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i64_v4f32 = uitofp <4 x i64> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i64_v4f64 = uitofp <4 x i64> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_v4f32 = uitofp <4 x i1> undef to <4 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_v4f64 = uitofp <4 x i1> undef to <4 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi8_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi8_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i8(<4 x i8> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi16_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi16_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i16(<4 x i16> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi32_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi32_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i32(<4 x i32> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi64_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi64_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i64(<4 x i64> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi1_v4f32 = call <4 x float> @llvm.vp.uitofp.v4f32.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %vp_v4fi1_v4f64 = call <4 x double> @llvm.vp.uitofp.v4f64.v4i1(<4 x i1> undef, <4 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i8_v8f32 = uitofp <8 x i8> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i8_v8f64 = uitofp <8 x i8> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i16_v8f32 = uitofp <8 x i16> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i16_v8f64 = uitofp <8 x i16> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i32_v8f32 = uitofp <8 x i32> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i32_v8f64 = uitofp <8 x i32> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i64_v8f32 = uitofp <8 x i64> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i64_v8f64 = uitofp <8 x i64> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i1_v8f32 = uitofp <8 x i1> undef to <8 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v8i1_v8f64 = uitofp <8 x i1> undef to <8 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi8_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi8_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i8(<8 x i8> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi16_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi16_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i16(<8 x i16> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi32_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi32_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i32(<8 x i32> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi64_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi64_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i64(<8 x i64> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi1_v8f32 = call <8 x float> @llvm.vp.uitofp.v8f32.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %vp_v8fi1_v8f64 = call <8 x double> @llvm.vp.uitofp.v8f64.v8i1(<8 x i1> undef, <8 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i8_v16f32 = uitofp <16 x i8> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i8_v16f64 = uitofp <16 x i8> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i16_v16f32 = uitofp <16 x i16> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i16_v16f64 = uitofp <16 x i16> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i32_v16f32 = uitofp <16 x i32> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i32_v16f64 = uitofp <16 x i32> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i64_v16f32 = uitofp <16 x i64> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i64_v16f64 = uitofp <16 x i64> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i1_v16f32 = uitofp <16 x i1> undef to <16 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v16i1_v16f64 = uitofp <16 x i1> undef to <16 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi8_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi8_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i8(<16 x i8> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi16_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi16_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i16(<16 x i16> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi32_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi32_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i32(<16 x i32> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi64_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi64_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i64(<16 x i64> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi1_v16f32 = call <16 x float> @llvm.vp.uitofp.v16f32.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %vp_v16fi1_v16f64 = call <16 x double> @llvm.vp.uitofp.v16f64.v16i1(<16 x i1> undef, <16 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i8_v32f32 = uitofp <32 x i8> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i8_v32f64 = uitofp <32 x i8> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i16_v32f32 = uitofp <32 x i16> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i16_v32f64 = uitofp <32 x i16> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i32_v32f32 = uitofp <32 x i32> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i32_v32f64 = uitofp <32 x i32> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32i64_v32f32 = uitofp <32 x i64> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v32i64_v32f64 = uitofp <32 x i64> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i1_v32f32 = uitofp <32 x i1> undef to <32 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v32i1_v32f64 = uitofp <32 x i1> undef to <32 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi8_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi8_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i8(<32 x i8> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi16_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi16_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i16(<32 x i16> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi32_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi32_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i32(<32 x i32> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32fi64_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %vp_v32fi64_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i64(<32 x i64> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi1_v32f32 = call <32 x float> @llvm.vp.uitofp.v32f32.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %vp_v32fi1_v32f64 = call <32 x double> @llvm.vp.uitofp.v32f64.v32i1(<32 x i1> undef, <32 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i8_v64f32 = uitofp <64 x i8> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i8_v64f64 = uitofp <64 x i8> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i16_v64f32 = uitofp <64 x i16> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i16_v64f64 = uitofp <64 x i16> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v64i32_v64f32 = uitofp <64 x i32> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v64i32_v64f64 = uitofp <64 x i32> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64i64_v64f32 = uitofp <64 x i64> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %v64i64_v64f64 = uitofp <64 x i64> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i1_v64f32 = uitofp <64 x i1> undef to <64 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %v64i1_v64f64 = uitofp <64 x i1> undef to <64 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi8_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi8_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i8(<64 x i8> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi16_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi16_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i16(<64 x i16> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %vp_v64fi32_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %vp_v64fi32_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i32(<64 x i32> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64fi64_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 124 for instruction: %vp_v64fi64_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i64(<64 x i64> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi1_v64f32 = call <64 x float> @llvm.vp.uitofp.v64f32.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 127 for instruction: %vp_v64fi1_v64f64 = call <64 x double> @llvm.vp.uitofp.v64f64.v64i1(<64 x i1> undef, <64 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i8_v128f32 = uitofp <128 x i8> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i8_v128f64 = uitofp <128 x i8> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v128i16_v128f32 = uitofp <128 x i16> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %v128i16_v128f64 = uitofp <128 x i16> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %v128i32_v128f32 = uitofp <128 x i32> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %v128i32_v128f64 = uitofp <128 x i32> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128i64_v128f32 = uitofp <128 x i64> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %v128i64_v128f64 = uitofp <128 x i64> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i1_v128f32 = uitofp <128 x i1> undef to <128 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %v128i1_v128f64 = uitofp <128 x i1> undef to <128 x double> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi8_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi8_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i8(<128 x i8> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v128fi16_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 254 for instruction: %vp_v128fi16_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i16(<128 x i16> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %vp_v128fi32_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 252 for instruction: %vp_v128fi32_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i32(<128 x i32> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128fi64_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 248 for instruction: %vp_v128fi64_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i64(<128 x i64> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi1_v128f32 = call <128 x float> @llvm.vp.uitofp.v128f32.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 255 for instruction: %vp_v128fi1_v128f64 = call <128 x double> @llvm.vp.uitofp.v128f64.v128i1(<128 x i1> undef, <128 x i1> undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i8_nxv1f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i8_nxv1f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i16_nxv1f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i16_nxv1f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i32_nxv1f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i32_nxv1f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i64_nxv1f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i64_nxv1f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i1_nxv1f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv1i1_nxv1f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi8_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi8_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi16_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi16_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi32_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi32_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi64_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi64_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi1_nxv1f32 = call @llvm.vp.uitofp.nxv1f32.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv1fi1_nxv1f64 = call @llvm.vp.uitofp.nxv1f64.nxv1i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i8_nxv2f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i8_nxv2f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i16_nxv2f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i16_nxv2f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i32_nxv2f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i32_nxv2f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i64_nxv2f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i64_nxv2f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i1_nxv2f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv2i1_nxv2f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi8_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi8_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi16_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi16_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi32_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi32_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi64_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi64_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi1_nxv2f32 = call @llvm.vp.uitofp.nxv2f32.nxv2i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv2fi1_nxv2f64 = call @llvm.vp.uitofp.nxv2f64.nxv2i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i8_nxv4f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i8_nxv4f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i16_nxv4f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i16_nxv4f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i32_nxv4f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i32_nxv4f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i64_nxv4f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i64_nxv4f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i1_nxv4f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv4i1_nxv4f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi8_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi8_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi16_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi16_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi32_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi32_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi64_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi64_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi1_nxv4f32 = call @llvm.vp.uitofp.nxv4f32.nxv4i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv4fi1_nxv4f64 = call @llvm.vp.uitofp.nxv4f64.nxv4i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i8_nxv8f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i8_nxv8f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i16_nxv8f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i16_nxv8f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i32_nxv8f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i32_nxv8f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i64_nxv8f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i64_nxv8f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i1_nxv8f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv8i1_nxv8f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi8_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi8_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi16_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi16_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi32_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi32_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi64_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi64_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi1_nxv8f32 = call @llvm.vp.uitofp.nxv8f32.nxv8i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv8fi1_nxv8f64 = call @llvm.vp.uitofp.nxv8f64.nxv8i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i8_nxv16f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i8_nxv16f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i16_nxv16f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i16_nxv16f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i32_nxv16f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i32_nxv16f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i64_nxv16f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i64_nxv16f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i1_nxv16f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv16i1_nxv16f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi8_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi8_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi16_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi16_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi32_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi32_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi64_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi64_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi1_nxv16f32 = call @llvm.vp.uitofp.nxv16f32.nxv16i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv16fi1_nxv16f64 = call @llvm.vp.uitofp.nxv16f64.nxv16i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i8_nxv32f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i8_nxv32f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i16_nxv32f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i16_nxv32f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i32_nxv32f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i32_nxv32f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i64_nxv32f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i64_nxv32f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i1_nxv32f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv32i1_nxv32f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi8_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi8_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi16_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi16_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi32_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi32_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi64_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi64_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi1_nxv32f32 = call @llvm.vp.uitofp.nxv32f32.nxv32i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv32fi1_nxv32f64 = call @llvm.vp.uitofp.nxv32f64.nxv32i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i16_nxv64f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i16_nxv64f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i32_nxv64f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i32_nxv64f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64f32 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64f64 = uitofp undef to +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi8_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi8_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i8( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi16_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi16_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i16( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi32_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi32_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i32( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi64_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi64_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i64( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi1_nxv64f32 = call @llvm.vp.uitofp.nxv64f32.nxv64i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Invalid cost for instruction: %vp_nxv64fi1_nxv64f64 = call @llvm.vp.uitofp.nxv64f64.nxv64i1( undef, undef, i32 undef) +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2i8_v2f32 = uitofp <2 x i8> undef to <2 x float> %v2i8_v2f64 = uitofp <2 x i8> undef to <2 x double> @@ -4807,32 +6114,59 @@ define void @uitofp() { } define void @oddvec_sizes() { -; CHECK-LABEL: 'oddvec_sizes' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = sext <3 x i8> undef to <3 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = sext <7 x i8> undef to <7 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = sext <15 x i8> undef to <15 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = zext <3 x i8> undef to <3 x i16> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = zext <7 x i8> undef to <7 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %6 = zext <15 x i8> undef to <15 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = trunc <3 x i32> undef to <3 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = trunc <7 x i32> undef to <7 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %9 = trunc <15 x i32> undef to <15 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %10 = bitcast <3 x i32> undef to <3 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %11 = bitcast <7 x i32> undef to <7 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %12 = bitcast <15 x i32> undef to <15 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = sitofp <3 x i32> undef to <3 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %14 = sitofp <7 x i32> undef to <7 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %15 = sitofp <15 x i32> undef to <15 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = uitofp <3 x i32> undef to <3 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %17 = uitofp <7 x i32> undef to <7 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %18 = uitofp <15 x i32> undef to <15 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = fptosi <3 x float> undef to <3 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = fptosi <7 x float> undef to <7 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = fptosi <15 x float> undef to <15 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = fptoui <3 x float> undef to <3 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %23 = fptoui <7 x float> undef to <7 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %24 = fptoui <15 x float> undef to <15 x i32> -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'oddvec_sizes' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = sext <3 x i8> undef to <3 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = sext <7 x i8> undef to <7 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = sext <15 x i8> undef to <15 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = zext <3 x i8> undef to <3 x i16> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = zext <7 x i8> undef to <7 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %6 = zext <15 x i8> undef to <15 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = trunc <3 x i32> undef to <3 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = trunc <7 x i32> undef to <7 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %9 = trunc <15 x i32> undef to <15 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %10 = bitcast <3 x i32> undef to <3 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %11 = bitcast <7 x i32> undef to <7 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %12 = bitcast <15 x i32> undef to <15 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = sitofp <3 x i32> undef to <3 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %14 = sitofp <7 x i32> undef to <7 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %15 = sitofp <15 x i32> undef to <15 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = uitofp <3 x i32> undef to <3 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %17 = uitofp <7 x i32> undef to <7 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %18 = uitofp <15 x i32> undef to <15 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = fptosi <3 x float> undef to <3 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %20 = fptosi <7 x float> undef to <7 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %21 = fptosi <15 x float> undef to <15 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = fptoui <3 x float> undef to <3 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %23 = fptoui <7 x float> undef to <7 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %24 = fptoui <15 x float> undef to <15 x i32> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'oddvec_sizes' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %1 = sext <3 x i8> undef to <3 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = sext <7 x i8> undef to <7 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = sext <15 x i8> undef to <15 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = zext <3 x i8> undef to <3 x i16> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = zext <7 x i8> undef to <7 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %6 = zext <15 x i8> undef to <15 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = trunc <3 x i32> undef to <3 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %8 = trunc <7 x i32> undef to <7 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %9 = trunc <15 x i32> undef to <15 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %10 = bitcast <3 x i32> undef to <3 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %11 = bitcast <7 x i32> undef to <7 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %12 = bitcast <15 x i32> undef to <15 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %13 = sitofp <3 x i32> undef to <3 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %14 = sitofp <7 x i32> undef to <7 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %15 = sitofp <15 x i32> undef to <15 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %16 = uitofp <3 x i32> undef to <3 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %17 = uitofp <7 x i32> undef to <7 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %18 = uitofp <15 x i32> undef to <15 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %19 = fptosi <3 x float> undef to <3 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %20 = fptosi <7 x float> undef to <7 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 73 for instruction: %21 = fptosi <15 x float> undef to <15 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %22 = fptoui <3 x float> undef to <3 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %23 = fptoui <7 x float> undef to <7 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 73 for instruction: %24 = fptoui <15 x float> undef to <15 x i32> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; sext <3 x i8> undef to <3 x i16> sext <7 x i8> undef to <7 x i32> @@ -4873,16 +6207,27 @@ define void @oddvec_sizes() { ; vector splitting. We previously crashed on this case due to an ; infinite recursion between cast costing and scalarization costing. define void @legalization_crash() { -; CHECK-LABEL: 'legalization_crash' -; CHECK-NEXT: Cost Model: Found an estimated cost of 16700 for instruction: %1 = bitcast <24 x i8> undef to <192 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %2 = trunc <192 x i8> undef to <192 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %3 = zext <192 x i1> undef to <192 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %4 = sext <192 x i1> undef to <192 x i8> -; CHECK-NEXT: Cost Model: Found an estimated cost of 948 for instruction: %5 = sitofp <192 x i1> undef to <192 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 948 for instruction: %6 = uitofp <192 x i1> undef to <192 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %7 = fptosi <192 x float> undef to <192 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %8 = fptoui <192 x float> undef to <192 x i1> -; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; ZVE64D-LABEL: 'legalization_crash' +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16700 for instruction: %1 = bitcast <24 x i8> undef to <192 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %2 = trunc <192 x i8> undef to <192 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %3 = zext <192 x i1> undef to <192 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %4 = sext <192 x i1> undef to <192 x i8> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 948 for instruction: %5 = sitofp <192 x i1> undef to <192 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 948 for instruction: %6 = uitofp <192 x i1> undef to <192 x float> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %7 = fptosi <192 x float> undef to <192 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %8 = fptoui <192 x float> undef to <192 x i1> +; ZVE64D-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; ZVE64X-LABEL: 'legalization_crash' +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16700 for instruction: %1 = bitcast <24 x i8> undef to <192 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %2 = trunc <192 x i8> undef to <192 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %3 = zext <192 x i1> undef to <192 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %4 = sext <192 x i1> undef to <192 x i8> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 192 for instruction: %5 = sitofp <192 x i1> undef to <192 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 192 for instruction: %6 = uitofp <192 x i1> undef to <192 x float> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %7 = fptosi <192 x float> undef to <192 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 16892 for instruction: %8 = fptoui <192 x float> undef to <192 x i1> +; ZVE64X-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; bitcast <24 x i8> undef to <192 x i1> trunc <192 x i8> undef to <192 x i1> @@ -4894,6 +6239,3 @@ define void @legalization_crash() { fptoui <192 x float> undef to <192 x i1> ret void } -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; RV32: {{.*}} -; RV64: {{.*}} diff --git a/llvm/test/CodeGen/AArch64/bti-ehpad.ll b/llvm/test/CodeGen/AArch64/bti-ehpad.ll new file mode 100644 index 0000000000000..dee4bd3ec8adf --- /dev/null +++ b/llvm/test/CodeGen/AArch64/bti-ehpad.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64-unknown-linux-gnu %s -o - | FileCheck %s + +; Purpose: With BTI enabled, the landing pad (%lpad) begins with an EH_LABEL and the +; first *executed* instruction is `bti j`. (BTI is inserted *after* the EH label and meta.) + +declare i32 @__gxx_personality_v0(...) +declare void @may_throw() + +define void @test() #0 personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: test: +; CHECK: .Lfunc_begin0: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 28, .Lexception0 +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: bti c +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: bl may_throw +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: // %bb.1: // %common.ret +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_2: // %lpad +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: bti j +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret +entry: + invoke void @may_throw() + to label %ret unwind label %lpad + +lpad: + landingpad { ptr, i32 } cleanup + ret void + +ret: + ret void +} + +attributes #0 = { noinline "branch-target-enforcement"="true" "target-features"="+bti" } diff --git a/llvm/test/CodeGen/AArch64/late-taildup-computed-goto.ll b/llvm/test/CodeGen/AArch64/late-taildup-computed-goto.ll new file mode 100644 index 0000000000000..381904f776604 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/late-taildup-computed-goto.ll @@ -0,0 +1,143 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -tail-dup-pred-size=2 -tail-dup-succ-size=2 -o - %s | FileCheck %s + +target triple = "arm64-apple-macosx13.0.0" + +@opcode.targets = local_unnamed_addr constant [6 x ptr] [ptr blockaddress(@test_interp, %op1.bb), ptr blockaddress(@test_interp, %op6.bb), ptr blockaddress(@test_interp, %loop.header), ptr blockaddress(@test_interp, %op2.bb), ptr blockaddress(@test_interp, %op4.bb), ptr blockaddress(@test_interp, %op5.bb)] + +define void @test_interp(ptr %frame, ptr %dst) { +; CHECK-LABEL: test_interp: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: stp x24, x23, [sp, #-64]! ; 16-byte Folded Spill +; CHECK-NEXT: stp x22, x21, [sp, #16] ; 16-byte Folded Spill +; CHECK-NEXT: stp x20, x19, [sp, #32] ; 16-byte Folded Spill +; CHECK-NEXT: stp x29, x30, [sp, #48] ; 16-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 64 +; CHECK-NEXT: .cfi_offset w30, -8 +; CHECK-NEXT: .cfi_offset w29, -16 +; CHECK-NEXT: .cfi_offset w19, -24 +; CHECK-NEXT: .cfi_offset w20, -32 +; CHECK-NEXT: .cfi_offset w21, -40 +; CHECK-NEXT: .cfi_offset w22, -48 +; CHECK-NEXT: .cfi_offset w23, -56 +; CHECK-NEXT: .cfi_offset w24, -64 +; CHECK-NEXT: Lloh0: +; CHECK-NEXT: adrp x21, _opcode.targets@PAGE +; CHECK-NEXT: Lloh1: +; CHECK-NEXT: add x21, x21, _opcode.targets@PAGEOFF +; CHECK-NEXT: mov x24, xzr +; CHECK-NEXT: add x8, x21, xzr, lsl #3 +; CHECK-NEXT: mov x19, x1 +; CHECK-NEXT: mov x20, x0 +; CHECK-NEXT: mov x23, xzr +; CHECK-NEXT: mov w22, #1 ; =0x1 +; CHECK-NEXT: add x24, x24, #1 +; CHECK-NEXT: br x8 +; CHECK-NEXT: Ltmp0: ; Block address taken +; CHECK-NEXT: LBB0_1: ; %loop.header +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: add x8, x21, x24, lsl #3 +; CHECK-NEXT: mov x20, xzr +; CHECK-NEXT: mov x23, xzr +; CHECK-NEXT: add x24, x24, #1 +; CHECK-NEXT: br x8 +; CHECK-NEXT: Ltmp1: ; Block address taken +; CHECK-NEXT: LBB0_2: ; %op1.bb +; CHECK-NEXT: str xzr, [x19] +; CHECK-NEXT: Ltmp2: ; Block address taken +; CHECK-NEXT: LBB0_3: ; %op6.bb +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: ldr x0, [x20, #-8]! +; CHECK-NEXT: ldr x8, [x0, #8] +; CHECK-NEXT: str x22, [x0] +; CHECK-NEXT: ldr x8, [x8, #48] +; CHECK-NEXT: blr x8 +; CHECK-NEXT: add x8, x21, x24, lsl #3 +; CHECK-NEXT: add x24, x24, #1 +; CHECK-NEXT: br x8 +; CHECK-NEXT: Ltmp3: ; Block address taken +; CHECK-NEXT: LBB0_4: ; %op2.bb +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: add x8, x21, x24, lsl #3 +; CHECK-NEXT: mov x20, xzr +; CHECK-NEXT: str x23, [x19] +; CHECK-NEXT: mov x23, xzr +; CHECK-NEXT: add x24, x24, #1 +; CHECK-NEXT: br x8 +; CHECK-NEXT: Ltmp4: ; Block address taken +; CHECK-NEXT: LBB0_5: ; %op4.bb +; CHECK-NEXT: Ltmp5: ; Block address taken +; CHECK-NEXT: LBB0_6: ; %op5.bb +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: str x23, [x19] +; CHECK-NEXT: ldur x8, [x23, #12] +; CHECK-NEXT: ldur x9, [x20, #-8] +; CHECK-NEXT: add x23, x23, #20 +; CHECK-NEXT: stp x8, x9, [x20, #-8] +; CHECK-NEXT: add x8, x21, x24, lsl #3 +; CHECK-NEXT: add x20, x20, #8 +; CHECK-NEXT: add x24, x24, #1 +; CHECK-NEXT: br x8 +; CHECK-NEXT: .loh AdrpAdd Lloh0, Lloh1 +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %op1.bb ], [ %iv.next, %op2.bb ], [ %iv.next, %op4.bb ], [ %iv.next, %op5.bb ], [ %iv.next, %op6.bb ], [ %iv.next, %loop.header ] + %stack.pointer = phi ptr [ %frame, %entry ], [ %stack.8, %op1.bb ], [ null, %op2.bb ], [ %stack.next, %op4.bb ], [ %stack.next.2, %op5.bb ], [ %stack.4, %op6.bb ], [ null, %loop.header ] + %next.instr = phi ptr [ null, %entry ], [ %next.instr, %op1.bb ], [ null, %op2.bb ], [ %next.instr.20, %op4.bb ], [ %next.instr.21, %op5.bb ], [ %next.instr, %op6.bb ], [ null, %loop.header ] + %iv.next = add i64 %iv, 1 + %next_op = getelementptr [6 x ptr], ptr @opcode.targets, i64 0, i64 %iv + indirectbr ptr %next_op, [label %op1.bb, label %op6.bb, label %loop.header, label %op2.bb, label %op4.bb, label %op5.bb] + +op1.bb: + store ptr null, ptr %dst, align 8 + %stack.8 = getelementptr i8, ptr %stack.pointer, i64 -8 + %l.0 = load ptr, ptr %stack.8, align 8 + store i64 1, ptr %l.0, align 8 + %gep.0 = getelementptr i8, ptr %l.0, i64 8 + %l.1 = load ptr, ptr %gep.0, align 8 + %gep.1 = getelementptr i8, ptr %l.1, i64 48 + %l.2 = load ptr, ptr %gep.1, align 8 + tail call void %l.2(ptr nonnull %l.0) + br label %loop.header + +op2.bb: + store ptr %next.instr, ptr %dst, align 8 + br label %loop.header + +op4.bb: + store ptr %next.instr, ptr %dst, align 8 + %next.instr.20 = getelementptr i8, ptr %next.instr, i64 20 + %stack.2 = getelementptr i8, ptr %stack.pointer, i64 -8 + %l.3 = load ptr, ptr %stack.2, align 8 + %next.instr.12 = getelementptr i8, ptr %next.instr, i64 12 + %next.instr.12.val = load ptr, ptr %next.instr.12, align 2 + store ptr %next.instr.12.val, ptr %stack.2, align 8 + store ptr %l.3, ptr %stack.pointer, align 8 + %stack.next = getelementptr i8, ptr %stack.pointer, i64 8 + br label %loop.header + +op5.bb: + store ptr %next.instr, ptr %dst, align 8 + %next.instr.21 = getelementptr i8, ptr %next.instr, i64 20 + %stack.3 = getelementptr i8, ptr %stack.pointer, i64 -8 + %l.4 = load ptr, ptr %stack.3, align 8 + %next.instr.2 = getelementptr i8, ptr %next.instr, i64 12 + %next.instr.2.val = load ptr, ptr %next.instr.2, align 2 + store ptr %next.instr.2.val, ptr %stack.3, align 8 + store ptr %l.4, ptr %stack.pointer, align 8 + %stack.next.2 = getelementptr i8, ptr %stack.pointer, i64 8 + br label %loop.header + +op6.bb: + %stack.4 = getelementptr i8, ptr %stack.pointer, i64 -8 + %l.5 = load ptr, ptr %stack.4, align 8 + store i64 1, ptr %l.5, align 8 + %gep.5 = getelementptr i8, ptr %l.5, i64 8 + %l.6 = load ptr, ptr %gep.5, align 8 + %gep.6 = getelementptr i8, ptr %l.6, i64 48 + %l.7 = load ptr, ptr %gep.6, align 8 + tail call void %l.7(ptr nonnull %l.5) + br label %loop.header +} diff --git a/llvm/test/CodeGen/AArch64/pr166870.ll b/llvm/test/CodeGen/AArch64/pr166870.ll new file mode 100644 index 0000000000000..dc23f51987635 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/pr166870.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc -O3 < %s -mtriple=aarch64 | FileCheck %s + +; The seemingly redundant mov where src_reg == dst_reg shouldn't be removed, +; because it has the effect of zeroing the upper bits in x8. + +define i32 @ham(i32 %arg, i1 %arg1, i1 %arg2, ptr %arg3) nounwind { +; CHECK-LABEL: ham: +; CHECK: // %bb.0: // %bb +; CHECK-NEXT: stp x30, x21, [sp, #-32]! // 16-byte Folded Spill +; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: tbnz w1, #0, .LBB0_3 +; CHECK-NEXT: // %bb.1: // %bb4 +; CHECK-NEXT: tbnz w2, #0, .LBB0_3 +; CHECK-NEXT: // %bb.2: // %bb5 +; CHECK-NEXT: mov x19, x3 +; CHECK-NEXT: mov w21, w1 +; CHECK-NEXT: mov w20, w0 +; CHECK-NEXT: bl zot +; CHECK-NEXT: tbz w21, #0, .LBB0_4 +; CHECK-NEXT: .LBB0_3: // %bb6 +; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ldp x30, x21, [sp], #32 // 16-byte Folded Reload +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: mov w8, w20 +; CHECK-NEXT: mov w20, wzr +; CHECK-NEXT: mov w8, w8 +; CHECK-NEXT: mov w21, w8 +; CHECK-NEXT: .LBB0_5: // %bb7 +; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: strb w20, [x19] +; CHECK-NEXT: cbnz x21, .LBB0_5 +; CHECK-NEXT: // %bb.6: // %bb8 +; CHECK-NEXT: // in Loop: Header=BB0_5 Depth=1 +; CHECK-NEXT: bl quux +; CHECK-NEXT: b .LBB0_5 +bb: + br i1 %arg1, label %bb6, label %bb4 + +bb4: + %load = load ptr, ptr null, align 8 + br i1 %arg2, label %bb6, label %bb5 + +bb5: + %call = call i32 @zot() #0 + %zext = zext i32 %arg to i64 + br i1 %arg1, label %bb6, label %bb7 + +bb6: + ret i32 0 + +bb7: + store i8 0, ptr %arg3, align 1 + %icmp = icmp eq i64 %zext, 0 + br i1 %icmp, label %bb8, label %bb7 + +bb8: + call void @quux() + br label %bb7 +} + +declare i32 @zot() + +declare void @quux() + +attributes #0 = { returns_twice } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-call.ll index 700686b9f194b..fc555a882be2c 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-call.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-call.ll @@ -181,8 +181,9 @@ define void @test_tailcall_omit_mov_x16_x16(ptr %objptr) #0 { ; ELF-NEXT: movk x8, #6503, lsl #48 ; ELF-NEXT: autda x1, x8 ; ELF-NEXT: ldr x2, [x1] -; ELF-NEXT: movk x1, #54167, lsl #48 -; ELF-NEXT: braa x2, x1 +; ELF-NEXT: mov x16, x1 +; ELF-NEXT: movk x16, #54167, lsl #48 +; ELF-NEXT: braa x2, x16 %vtable.signed = load ptr, ptr %objptr, align 8 %objptr.int = ptrtoint ptr %objptr to i64 %vtable.discr = tail call i64 @llvm.ptrauth.blend(i64 %objptr.int, i64 6503) @@ -213,8 +214,9 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 { ; ELF-NEXT: movk x9, #6503, lsl #48 ; ELF-NEXT: autda x8, x9 ; ELF-NEXT: ldr x9, [x8] -; ELF-NEXT: movk x8, #34646, lsl #48 -; ELF-NEXT: blraa x9, x8 +; ELF-NEXT: mov x17, x8 +; ELF-NEXT: movk x17, #34646, lsl #48 +; ELF-NEXT: blraa x9, x17 ; ELF-NEXT: mov w0, #42 ; ELF-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: ret @@ -230,6 +232,97 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 { ret i32 42 } +; The second BLRA instruction should not reuse its AddrDisc operand as a scratch register (returned later). +define i64 @test_call_discr_csr_live(ptr %fnptr, i64 %addr.discr) #0 { +; ELF-LABEL: test_call_discr_csr_live: +; ELF-NEXT: str x30, [sp, #-32]! +; ELF-NEXT: stp x20, x19, [sp, #16] +; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0 +; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1 +; ELF-DAG: mov x17, x1 +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x0, x17 +; ELF-NEXT: mov x17, x[[ADDR_DISC]] +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x[[FNPTR]], x17 +; ELF-NEXT: mov x0, x[[ADDR_DISC]] +; ELF-NEXT: ldp x20, x19, [sp, #16] +; ELF-NEXT: ldr x30, [sp], #32 +; ELF-NEXT: ret + %discr = tail call i64 @llvm.ptrauth.blend(i64 %addr.discr, i64 6503) + tail call void %fnptr() [ "ptrauth"(i32 0, i64 %discr) ] + tail call void %fnptr() [ "ptrauth"(i32 0, i64 %discr) ] + ret i64 %addr.discr +} + +; The second BLRA instruction may reuse its AddrDisc operand as a scratch register. +define i64 @test_call_discr_csr_killed(ptr %fnptr, i64 %addr.discr) #0 { +; ELF-LABEL: test_call_discr_csr_killed: +; ELF-NEXT: str x30, [sp, #-32]! +; ELF-NEXT: stp x20, x19, [sp, #16] +; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0 +; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1 +; ELF-DAG: mov x17, x1 +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x0, x17 +; ELF-DAG: mov x17, x[[ADDR_DISC]] +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x[[FNPTR]], x17 +; ELF-NEXT: ldp x20, x19, [sp, #16] +; ELF-NEXT: mov w0, #42 +; ELF-NEXT: ldr x30, [sp], #32 +; ELF-NEXT: ret + %discr = tail call i64 @llvm.ptrauth.blend(i64 %addr.discr, i64 6503) + tail call void %fnptr() [ "ptrauth"(i32 0, i64 %discr) ] + tail call void %fnptr() [ "ptrauth"(i32 0, i64 %discr) ] + ret i64 42 +} + +; BLRA instruction should not reuse its AddrDisc operand as a scratch register (function argument). +define i64 @test_call_discr_arg(ptr %fnptr, i64 %addr.discr) #0 { +; ELF-LABEL: test_call_discr_arg: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: mov x8, x0 +; ELF-NEXT: mov x0, xzr +; ELF-NEXT: mov x17, x1 +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x8, x17 +; ELF-NEXT: mov w0, #42 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %discr = tail call i64 @llvm.ptrauth.blend(i64 %addr.discr, i64 6503) + tail call void %fnptr(ptr null, i64 %addr.discr) [ "ptrauth"(i32 0, i64 %discr) ] + ret i64 42 +} + +; BLRA instruction may reuse its AddrDisc operand as a scratch register. +define i64 @test_call_discr_non_arg(ptr %fnptr, i64 %addr.discr) #0 { +; ELF-LABEL: test_call_discr_non_arg: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: mov x17, x1 +; ELF-NEXT: movk x17, #6503, lsl #48 +; ELF-NEXT: blraa x0, x17 +; ELF-NEXT: mov w0, #42 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %discr = tail call i64 @llvm.ptrauth.blend(i64 %addr.discr, i64 6503) + tail call void %fnptr() [ "ptrauth"(i32 0, i64 %discr) ] + ret i64 42 +} + +; AUTH_TCRETURN instruction should not reuse its AddrDisc operand as a scratch register (function argument). +define i64 @test_tailcall_discr_arg(ptr %fnptr, i64 %addr.discr) #0 { +; ELF-LABEL: test_tailcall_discr_arg: +; ELF-NEXT: mov x2, x0 +; ELF-NEXT: mov x0, xzr +; ELF-NEXT: mov x16, x1 +; ELF-NEXT: movk x16, #6503, lsl #48 +; ELF-NEXT: braa x2, x16 + %discr = tail call i64 @llvm.ptrauth.blend(i64 %addr.discr, i64 6503) + %result = tail call i64 %fnptr(ptr null, i64 %addr.discr) [ "ptrauth"(i32 0, i64 %discr) ] + ret i64 %result +} + define i32 @test_call_ia_arg(ptr %arg0, i64 %arg1) #0 { ; DARWIN-LABEL: test_call_ia_arg: ; DARWIN-NEXT: stp x29, x30, [sp, #-16]! diff --git a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll index 2634beb4e3591..52b38a5632005 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll @@ -755,5 +755,128 @@ define i64 @test_auth_ia_swapped(i64 %arg, i64 %arg1) { ret i64 %tmp } +; Authentications should not be speculated, as they crash on failure and it is +; perfectly correct to dynamically choose the signing schema or whether to +; perform authentication at all. +define ptr @auth_speculation(i64 %signed, i1 %cond) { +; UNCHECKED-LABEL: auth_speculation: +; UNCHECKED: %bb.0: +; UNCHECKED-DARWIN-NEXT: mov x16, x0 +; UNCHECKED-DARWIN-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; UNCHECKED-DARWIN-NEXT: %bb.1: +; UNCHECKED-DARWIN-NEXT: autdza x16 +; UNCHECKED-DARWIN-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; UNCHECKED-DARWIN-NEXT: [[BB_ELSE]]: +; UNCHECKED-DARWIN-NEXT: autdzb x16 +; UNCHECKED-DARWIN-NEXT: [[BB_RETURN]]: +; UNCHECKED-DARWIN-NEXT: ldr x8, [x16] +; UNCHECKED-ELF-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; UNCHECKED-ELF-NEXT: %bb.1: +; UNCHECKED-ELF-NEXT: autdza x0 +; UNCHECKED-ELF-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; UNCHECKED-ELF-NEXT: [[BB_ELSE]]: +; UNCHECKED-ELF-NEXT: autdzb x0 +; UNCHECKED-ELF-NEXT: [[BB_RETURN]]: +; UNCHECKED-ELF-NEXT: ldr x8, [x0] +; UNCHECKED-NEXT: ldr x8, [x8] +; UNCHECKED-NEXT: ldr x8, [x8] +; UNCHECKED-NEXT: ldr x0, [x8] +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: auth_speculation: +; CHECKED: %bb.0: +; CHECKED-DARWIN-NEXT: mov x16, x0 +; CHECKED-DARWIN-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; CHECKED-DARWIN-NEXT: %bb.1: +; CHECKED-DARWIN-NEXT: autdza x16 +; CHECKED-DARWIN-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; CHECKED-DARWIN-NEXT: [[BB_ELSE]]: +; CHECKED-DARWIN-NEXT: autdzb x16 +; CHECKED-DARWIN-NEXT: [[BB_RETURN]]: +; CHECKED-DARWIN-NEXT: ldr x8, [x16] +; CHECKED-ELF-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; CHECKED-ELF-NEXT: %bb.1: +; CHECKED-ELF-NEXT: autdza x0 +; CHECKED-ELF-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; CHECKED-ELF-NEXT: [[BB_ELSE]]: +; CHECKED-ELF-NEXT: autdzb x0 +; CHECKED-ELF-NEXT: [[BB_RETURN]]: +; CHECKED-ELF-NEXT: ldr x8, [x0] +; CHECKED-NEXT: ldr x8, [x8] +; CHECKED-NEXT: ldr x8, [x8] +; CHECKED-NEXT: ldr x0, [x8] +; CHECKED-NEXT: ret +; +; TRAP-LABEL: auth_speculation: +; TRAP: %bb.0: +; TRAP-DARWIN-NEXT: mov x16, x0 +; TRAP-DARWIN-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; TRAP-DARWIN-NEXT: %bb.1: +; TRAP-DARWIN-NEXT: autdza x16 +; TRAP-DARWIN-NEXT: mov x17, x16 +; TRAP-DARWIN-NEXT: xpacd x17 +; TRAP-DARWIN-NEXT: cmp x16, x17 +; TRAP-DARWIN-NEXT: b.eq [[L]]auth_success_18 +; TRAP-DARWIN-NEXT: brk #0xc472 +; TRAP-DARWIN-NEXT: [[L]]auth_success_18: +; TRAP-DARWIN-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; TRAP-DARWIN-NEXT: [[BB_ELSE]]: +; TRAP-DARWIN-NEXT: autdzb x16 +; TRAP-DARWIN-NEXT: mov x17, x16 +; TRAP-DARWIN-NEXT: xpacd x17 +; TRAP-DARWIN-NEXT: cmp x16, x17 +; TRAP-DARWIN-NEXT: b.eq [[L]]auth_success_19 +; TRAP-DARWIN-NEXT: brk #0xc473 +; TRAP-DARWIN-NEXT: [[L]]auth_success_19: +; TRAP-DARWIN-NEXT: [[BB_RETURN]]: +; TRAP-DARWIN-NEXT: ldr x8, [x16] +; TRAP-ELF-NEXT: tbz w1, #0, [[BB_ELSE:[A-Za-z0-9_.]+]] +; TRAP-ELF-NEXT: %bb.1: +; TRAP-ELF-NEXT: autdza x0 +; TRAP-ELF-NEXT: mov x8, x0 +; TRAP-ELF-NEXT: xpacd x8 +; TRAP-ELF-NEXT: cmp x0, x8 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_18 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: [[L]]auth_success_18: +; TRAP-ELF-NEXT: b [[BB_RETURN:[A-Za-z0-9_.]+]] +; TRAP-ELF-NEXT: [[BB_ELSE]]: +; TRAP-ELF-NEXT: autdzb x0 +; TRAP-ELF-NEXT: mov x8, x0 +; TRAP-ELF-NEXT: xpacd x8 +; TRAP-ELF-NEXT: cmp x0, x8 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_19 +; TRAP-ELF-NEXT: brk #0xc473 +; TRAP-ELF-NEXT: [[L]]auth_success_19: +; TRAP-ELF-NEXT: [[BB_RETURN]]: +; TRAP-ELF-NEXT: ldr x8, [x0] +; TRAP-NEXT: ldr x8, [x8] +; TRAP-NEXT: ldr x8, [x8] +; TRAP-NEXT: ldr x0, [x8] +; TRAP-NEXT: ret +entry: + br i1 %cond, label %if.then, label %if.else + +if.then: + %auted.then = tail call i64 @llvm.ptrauth.auth(i64 %signed, i32 2, i64 0) + br label %return + +if.else: + %auted.else = tail call i64 @llvm.ptrauth.auth(i64 %signed, i32 3, i64 0) + br label %return + +return: + %auted = phi i64 [ %auted.then, %if.then ], [ %auted.else, %if.else ] + + ; A sequence of instructions that is common to both "then" and "else" + ; branches and is expensive to duplicate. + %ptr.0 = inttoptr i64 %auted to ptr + %ptr.1 = load ptr, ptr %ptr.0 + %ptr.2 = load ptr, ptr %ptr.1 + %ptr.3 = load ptr, ptr %ptr.2 + %ptr.4 = load ptr, ptr %ptr.3 + ret ptr %ptr.4 +} + declare i64 @llvm.ptrauth.auth(i64, i32, i64) declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64) diff --git a/llvm/test/CodeGen/AArch64/selectopt-cast.ll b/llvm/test/CodeGen/AArch64/selectopt-cast.ll index b862458e99fe2..47cc736ad6880 100644 --- a/llvm/test/CodeGen/AArch64/selectopt-cast.ll +++ b/llvm/test/CodeGen/AArch64/selectopt-cast.ll @@ -901,3 +901,49 @@ loop: exit: ret void } + +define void @sext_i128() { +; CHECK-LABEL: @sext_i128( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[I:%.*]] = icmp slt i128 0, 0 +; CHECK-NEXT: [[I2:%.*]] = sext i1 [[I]] to i128 +; CHECK-NEXT: [[I3:%.*]] = or i128 [[I2]], 0 +; CHECK-NEXT: [[I4:%.*]] = icmp slt i128 [[I3]], 0 +; CHECK-NEXT: [[I5:%.*]] = sext i1 [[I4]] to i128 +; CHECK-NEXT: [[I4_FROZEN:%.*]] = freeze i1 [[I4]] +; CHECK-NEXT: br i1 [[I4_FROZEN]], label [[SELECT_TRUE_SINK:%.*]], label [[SELECT_END:%.*]] +; CHECK: select.true.sink: +; CHECK-NEXT: [[TMP0:%.*]] = add i128 -1, 0 +; CHECK-NEXT: br label [[SELECT_END]] +; CHECK: select.end: +; CHECK-NEXT: [[I6:%.*]] = phi i128 [ [[TMP0]], [[SELECT_TRUE_SINK]] ], [ 0, [[LOOP]] ] +; CHECK-NEXT: [[I7:%.*]] = icmp slt i128 [[I6]], 0 +; CHECK-NEXT: [[I8:%.*]] = sext i1 [[I7]] to i128 +; CHECK-NEXT: [[I7_FROZEN:%.*]] = freeze i1 [[I7]] +; CHECK-NEXT: br i1 [[I7_FROZEN]], label [[SELECT_TRUE_SINK2:%.*]], label [[SELECT_END1:%.*]] +; CHECK: select.true.sink2: +; CHECK-NEXT: [[TMP1:%.*]] = add i128 -1, 0 +; CHECK-NEXT: br label [[SELECT_END1]] +; CHECK: select.end1: +; CHECK-NEXT: [[I9:%.*]] = phi i128 [ [[TMP1]], [[SELECT_TRUE_SINK2]] ], [ 0, [[SELECT_END]] ] +; CHECK-NEXT: [[I10:%.*]] = or i128 [[I9]], 0 +; CHECK-NEXT: br label [[LOOP]] +; +entry: + br label %loop + +loop: + %i = icmp slt i128 0, 0 + %i2 = sext i1 %i to i128 + %i3 = or i128 %i2, 0 + %i4 = icmp slt i128 %i3, 0 + %i5 = sext i1 %i4 to i128 + %i6 = add i128 %i5, 0 + %i7 = icmp slt i128 %i6, 0 + %i8 = sext i1 %i7 to i128 + %i9 = add i128 %i8, 0 + %i10 = or i128 %i9, 0 + br label %loop +} diff --git a/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll b/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll index 85aa6846cd800..0091469edde92 100644 --- a/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll +++ b/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll @@ -507,8 +507,8 @@ define i32 @leaf_sign_all_a_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-r ; ; PAUTHLR-LABEL: leaf_sign_all_a_key_bti: ; PAUTHLR: // %bb.0: -; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .cfi_negate_ra_state_with_pc +; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .Ltmp10: ; PAUTHLR-NEXT: paciasppc ; PAUTHLR-NEXT: adrp x16, .Ltmp10 @@ -521,8 +521,8 @@ define i32 @leaf_sign_all_a_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-r define i32 @leaf_sign_all_b_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-return-address"="all" "sign-return-address-key"="b_key" "branch-target-enforcement" { ; COMPAT-LABEL: leaf_sign_all_b_key_bti: ; COMPAT: // %bb.0: +; COMPAT-NEXT: .cfi_b_key_frame ; COMPAT-NEXT: hint #34 -; COMPAT-NEXT: .cfi_b_key_frame ; COMPAT-NEXT: hint #39 ; COMPAT-NEXT: .cfi_negate_ra_state_with_pc ; COMPAT-NEXT: .Ltmp11: @@ -535,8 +535,8 @@ define i32 @leaf_sign_all_b_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-r ; ; V83A-LABEL: leaf_sign_all_b_key_bti: ; V83A: // %bb.0: -; V83A-NEXT: hint #34 ; V83A-NEXT: .cfi_b_key_frame +; V83A-NEXT: hint #34 ; V83A-NEXT: hint #39 ; V83A-NEXT: .cfi_negate_ra_state_with_pc ; V83A-NEXT: .Ltmp11: @@ -548,9 +548,9 @@ define i32 @leaf_sign_all_b_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-r ; ; PAUTHLR-LABEL: leaf_sign_all_b_key_bti: ; PAUTHLR: // %bb.0: -; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .cfi_b_key_frame ; PAUTHLR-NEXT: .cfi_negate_ra_state_with_pc +; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .Ltmp11: ; PAUTHLR-NEXT: pacibsppc ; PAUTHLR-NEXT: adrp x16, .Ltmp11 @@ -563,9 +563,9 @@ define i32 @leaf_sign_all_b_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-r define i32 @leaf_sign_all_v83_b_key_bti(i32 %x) "branch-protection-pauth-lr" "sign-return-address"="all" "target-features"="+v8.3a" "sign-return-address-key"="b_key" "branch-target-enforcement" { ; CHECK-LABEL: leaf_sign_all_v83_b_key_bti: ; CHECK: // %bb.0: -; CHECK-NEXT: hint #34 -; CHECK-NEXT: .cfi_b_key_frame -; CHECK-NEXT: hint #39 +; CHECK-NEXT: .cfi_b_key_frame +; CHECK-NEXT: hint #34 +; CHECK-NEXT: hint #39 ; CHECK-NEXT: .cfi_negate_ra_state_with_pc ; CHECK-NEXT: .Ltmp12: ; CHECK-NEXT: pacibsp @@ -576,9 +576,9 @@ define i32 @leaf_sign_all_v83_b_key_bti(i32 %x) "branch-protection-pauth-lr" "si ; ; PAUTHLR-LABEL: leaf_sign_all_v83_b_key_bti: ; PAUTHLR: // %bb.0: -; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .cfi_b_key_frame ; PAUTHLR-NEXT: .cfi_negate_ra_state_with_pc +; PAUTHLR-NEXT: bti c ; PAUTHLR-NEXT: .Ltmp12: ; PAUTHLR-NEXT: pacibsppc ; PAUTHLR-NEXT: adrp x16, .Ltmp12 diff --git a/llvm/test/CodeGen/AArch64/spillfill-sve.mir b/llvm/test/CodeGen/AArch64/spillfill-sve.mir index 83c9b73c57570..2b16dd0f29ecc 100644 --- a/llvm/test/CodeGen/AArch64/spillfill-sve.mir +++ b/llvm/test/CodeGen/AArch64/spillfill-sve.mir @@ -1,5 +1,5 @@ -# RUN: llc -mtriple=aarch64-linux-gnu -run-pass=greedy %s -o - | FileCheck %s -# RUN: llc -mtriple=aarch64-linux-gnu -start-before=greedy -stop-after=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=EXPAND +# RUN: llc -mtriple=aarch64-linux-gnu -run-pass=greedy -aarch64-stack-hazard-size=0 %s -o - | FileCheck %s +# RUN: llc -mtriple=aarch64-linux-gnu -start-before=greedy -stop-after=aarch64-expand-pseudo -verify-machineinstrs -aarch64-stack-hazard-size=0 %s -o - | FileCheck %s --check-prefix=EXPAND --- | ; ModuleID = '' source_filename = "" @@ -14,13 +14,14 @@ define aarch64_sve_vector_pcs void @spills_fills_stack_id_virtreg_ppr_to_pnr() #1 { entry: unreachable } define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr() #0 { entry: unreachable } define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr2() #0 { entry: unreachable } - define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr2strided() #0 { entry: unreachable } + define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr2strided() #2 { entry: unreachable } define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr3() #0 { entry: unreachable } define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr4() #0 { entry: unreachable } - define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr4strided() #0 { entry: unreachable } + define aarch64_sve_vector_pcs void @spills_fills_stack_id_zpr4strided() #2 { entry: unreachable } attributes #0 = { nounwind "target-features"="+sve" } attributes #1 = { nounwind "target-features"="+sve2p1" } + attributes #2 = { nounwind "target-features"="+sve,+sme2" "aarch64_pstate_sm_enabled" } ... --- @@ -318,10 +319,10 @@ registers: - { id: 0, class: zpr2 } stack: liveins: - - { reg: '$z0_z1', virtual-reg: '%0' } + - { reg: '$z1_z2', virtual-reg: '%0' } body: | bb.0.entry: - liveins: $z0_z1 + liveins: $z1_z2 ; CHECK-LABEL: name: spills_fills_stack_id_zpr2 ; CHECK: stack: @@ -329,12 +330,12 @@ body: | ; CHECK-NEXT: stack-id: scalable-vector ; EXPAND-LABEL: name: spills_fills_stack_id_zpr2 - ; EXPAND: STR_ZXI $z0, $sp, 0 - ; EXPAND: STR_ZXI $z1, $sp, 1 - ; EXPAND: $z0 = LDR_ZXI $sp, 0 - ; EXPAND: $z1 = LDR_ZXI $sp, 1 + ; EXPAND: STR_ZXI $z1, $sp, 0 + ; EXPAND: STR_ZXI $z2, $sp, 1 + ; EXPAND: $z1 = LDR_ZXI $sp, 0 + ; EXPAND: $z2 = LDR_ZXI $sp, 1 - %0:zpr2 = COPY $z0_z1 + %0:zpr2 = COPY $z1_z2 $z0_z1_z2_z3 = IMPLICIT_DEF $z4_z5_z6_z7 = IMPLICIT_DEF @@ -345,7 +346,7 @@ body: | $z24_z25_z26_z27 = IMPLICIT_DEF $z28_z29_z30_z31 = IMPLICIT_DEF - $z0_z1 = COPY %0 + $z1_z2 = COPY %0 RET_ReallyLR ... --- @@ -439,10 +440,10 @@ registers: - { id: 0, class: zpr4 } stack: liveins: - - { reg: '$z0_z1_z2_z3', virtual-reg: '%0' } + - { reg: '$z1_z2_z3_z4', virtual-reg: '%0' } body: | bb.0.entry: - liveins: $z0_z1_z2_z3 + liveins: $z1_z2_z3_z4 ; CHECK-LABEL: name: spills_fills_stack_id_zpr4 ; CHECK: stack: @@ -450,16 +451,16 @@ body: | ; CHECK-NEXT: stack-id: scalable-vector ; EXPAND-LABEL: name: spills_fills_stack_id_zpr4 - ; EXPAND: STR_ZXI $z0, $sp, 0 - ; EXPAND: STR_ZXI $z1, $sp, 1 - ; EXPAND: STR_ZXI $z2, $sp, 2 - ; EXPAND: STR_ZXI $z3, $sp, 3 - ; EXPAND: $z0 = LDR_ZXI $sp, 0 - ; EXPAND: $z1 = LDR_ZXI $sp, 1 - ; EXPAND: $z2 = LDR_ZXI $sp, 2 - ; EXPAND: $z3 = LDR_ZXI $sp, 3 + ; EXPAND: STR_ZXI $z1, $sp, 0 + ; EXPAND: STR_ZXI $z2, $sp, 1 + ; EXPAND: STR_ZXI $z3, $sp, 2 + ; EXPAND: STR_ZXI $z4, $sp, 3 + ; EXPAND: $z1 = LDR_ZXI $sp, 0 + ; EXPAND: $z2 = LDR_ZXI $sp, 1 + ; EXPAND: $z3 = LDR_ZXI $sp, 2 + ; EXPAND: $z4 = LDR_ZXI $sp, 3 - %0:zpr4 = COPY $z0_z1_z2_z3 + %0:zpr4 = COPY $z1_z2_z3_z4 $z0_z1_z2_z3 = IMPLICIT_DEF $z4_z5_z6_z7 = IMPLICIT_DEF @@ -470,7 +471,7 @@ body: | $z24_z25_z26_z27 = IMPLICIT_DEF $z28_z29_z30_z31 = IMPLICIT_DEF - $z0_z1_z2_z3 = COPY %0 + $z1_z2_z3_z4 = COPY %0 RET_ReallyLR ... --- diff --git a/llvm/test/CodeGen/AArch64/sve-pseudos-expand-undef.mir b/llvm/test/CodeGen/AArch64/sve-pseudos-expand-undef.mir index ae70f91a4ec64..a1d615c910792 100644 --- a/llvm/test/CodeGen/AArch64/sve-pseudos-expand-undef.mir +++ b/llvm/test/CodeGen/AArch64/sve-pseudos-expand-undef.mir @@ -12,7 +12,7 @@ body: | bb.0: liveins: $p0, $z0 - ; CHECK: add_x + ; CHECK: name: add_x ; CHECK-NOT: MOVPRFX ; CHECK: $z0 = FADD_ZPmZ_S renamable $p0, killed $z0, renamable $z0 ; CHECK-NEXT: RET @@ -21,22 +21,36 @@ body: | ... -# CHECK: {{.*}} MSB_ZPmZZ_B {{.*}} --- name: expand_mls_to_msb body: | bb.0: + ; CHECK: name: expand_mls_to_msb + ; CHECK: {{.*}} MSB_ZPmZZ_B {{.*}} renamable $p0 = PTRUE_B 31, implicit $vg renamable $z0 = MLS_ZPZZZ_B_UNDEF killed renamable $p0, killed renamable $z2, killed renamable $z0, killed renamable $z1 RET_ReallyLR implicit $z0 ... -# CHECK: {{.*}} MAD_ZPmZZ_B {{.*}} --- name: expand_mla_to_mad body: | bb.0: + ; CHECK: name: expand_mla_to_mad + ; CHECK: {{.*}} MAD_ZPmZZ_B {{.*}} renamable $p0 = PTRUE_B 31, implicit $vg renamable $z0 = MLA_ZPZZZ_B_UNDEF killed renamable $p0, killed renamable $z2, killed renamable $z0, killed renamable $z1 RET_ReallyLR implicit $z0 ... + +--- +name: expand_transfer_implicit_defs +body: | + bb.0: + ; CHECK: name: expand_transfer_implicit_defs + ; CHECK: BUNDLE + ; CHECK-SAME: implicit-def $z0_z1_z2_z3 + liveins: $z1, $z2, $p0 + renamable $z0 = FADD_ZPZZ_D_UNDEF killed $p0, killed $z1, killed $z2, implicit-def $z0_z1_z2_z3 + RET_ReallyLR implicit $z0_z1_z2_z3 +... diff --git a/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll b/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll new file mode 100644 index 0000000000000..3a1eaf04af5ab --- /dev/null +++ b/llvm/test/CodeGen/AArch64/wineh-bti-funclet.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64-windows -mattr=+bti -o - %s | FileCheck %s + +declare i32 @__CxxFrameHandler3(...) +declare void @may_throw() + +; Purpose: For WinEH funclets, entry is call-like: accept `bti c` / `hint #34` or a PAC prologue. + +define dso_local void @wineh_funclet() #0 personality ptr @__CxxFrameHandler3 { +; CHECK-LABEL: wineh_funclet: +; CHECK: .Lfunc_begin0: +; CHECK-NEXT: .seh_proc wineh_funclet +; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except +; CHECK-NEXT: // %bb.0: // %entry +; CHECK-NEXT: bti c +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 32 +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: .seh_set_fp +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: mov x0, #-2 // =0xfffffffffffffffe +; CHECK-NEXT: stur x0, [x29, #16] +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: bl may_throw +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: .LBB0_1: // Block address taken +; CHECK-NEXT: // %try.cont +; CHECK-NEXT: $ehgcr_0_1: +; CHECK-NEXT: bti j +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 32 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +; CHECK-NEXT: .seh_endfunclet +; CHECK-NEXT: .seh_handlerdata +; CHECK-NEXT: .word $cppxdata$wineh_funclet@IMGREL +; CHECK-NEXT: .text +; CHECK-NEXT: .seh_endproc +; CHECK-NEXT: .def "?catch$2@?0?wineh_funclet@4HA"; +; CHECK-NEXT: .scl 3; +; CHECK-NEXT: .type 32; +; CHECK-NEXT: .endef +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: "?catch$2@?0?wineh_funclet@4HA": +; CHECK-NEXT: .seh_proc "?catch$2@?0?wineh_funclet@4HA" +; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except +; CHECK-NEXT: .LBB0_2: // %catch +; CHECK-NEXT: bti c +; CHECK-NEXT: .seh_nop +; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endprologue +; CHECK-NEXT: bl may_throw +; CHECK-NEXT: adrp x0, .LBB0_1 +; CHECK-NEXT: add x0, x0, .LBB0_1 +; CHECK-NEXT: .seh_startepilogue +; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload +; CHECK-NEXT: .seh_save_fplr_x 16 +; CHECK-NEXT: .seh_endepilogue +; CHECK-NEXT: ret +entry: + invoke void @may_throw() + to label %try.cont unwind label %catch.dispatch + +catch.dispatch: + %cs = catchswitch within none [label %catch] unwind to caller + +catch: + %cp = catchpad within %cs [ptr null, i32 0, ptr null] + call void @may_throw() ["funclet"(token %cp)] + catchret from %cp to label %try.cont + +try.cont: + ret void +} + +attributes #0 = { noinline "branch-target-enforcement"="true" } diff --git a/llvm/test/CodeGen/AArch64/wineh-bti.ll b/llvm/test/CodeGen/AArch64/wineh-bti.ll index 8b8960d37f9ef..86555a7f64366 100644 --- a/llvm/test/CodeGen/AArch64/wineh-bti.ll +++ b/llvm/test/CodeGen/AArch64/wineh-bti.ll @@ -29,7 +29,7 @@ lbl4: ; CHECK-LABEL: func: ; CHECK-NEXT: .seh_proc func -; CHECK-NEXT: // %bb.0: +; CHECK: // %bb.0: // %entry ; CHECK-NEXT: hint #34 ; CHECK-NEXT: .seh_nop ; CHECK-NEXT: str x19, [sp, #-16]! diff --git a/llvm/test/CodeGen/AMDGPU/div_i128.ll b/llvm/test/CodeGen/AMDGPU/div_i128.ll index f8e13fcdd2273..51398a45055eb 100644 --- a/llvm/test/CodeGen/AMDGPU/div_i128.ll +++ b/llvm/test/CodeGen/AMDGPU/div_i128.ll @@ -475,28 +475,21 @@ define i128 @v_sdiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v5, v8 +; GFX9-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-O0-NEXT: s_nop 0 +; GFX9-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 def $vgpr7_vgpr8 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v8, v6 -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v8 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v7 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v5 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v4 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill ; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_mov_b64 s[8:9], s[6:7] -; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[8:9] +; GFX9-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[6:7] ; GFX9-O0-NEXT: s_mov_b64 s[12:13], 0x7f -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[12:13] -; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[14:15] +; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[12:13] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[14:15] -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[6:7] -; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[14:15] +; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[6:7] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[14:15] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, v6, v9, s[8:9] ; GFX9-O0-NEXT: v_and_b32_e64 v6, 1, v6 @@ -507,7 +500,6 @@ define i128 @v_sdiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: v_mov_b32_e32 v6, v5 ; GFX9-O0-NEXT: s_mov_b32 s14, s13 ; GFX9-O0-NEXT: v_xor_b32_e64 v6, v6, s14 -; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 killed $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: ; kill: def $sgpr12 killed $sgpr12 killed $sgpr12_sgpr13 ; GFX9-O0-NEXT: v_xor_b32_e64 v4, v4, s12 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec @@ -1043,10 +1035,10 @@ define i128 @v_sdiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload ; GFX9-O0-NEXT: s_mov_b64 s[6:7], 1 ; GFX9-O0-NEXT: s_mov_b32 s5, s6 ; GFX9-O0-NEXT: s_waitcnt vmcnt(1) @@ -2664,28 +2656,21 @@ define i128 @v_udiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v5, v8 +; GFX9-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-O0-NEXT: s_nop 0 +; GFX9-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 def $vgpr7_vgpr8 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v8, v6 -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v8 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v7 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v5 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v4 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill ; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_mov_b64 s[8:9], s[6:7] -; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[8:9] +; GFX9-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[6:7] ; GFX9-O0-NEXT: s_mov_b64 s[12:13], 0x7f -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[12:13] -; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[14:15] +; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[12:13] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[14:15] -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[6:7] -; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[14:15] +; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[6:7] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[14:15] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, v6, v9, s[8:9] ; GFX9-O0-NEXT: v_and_b32_e64 v6, 1, v6 @@ -2696,7 +2681,6 @@ define i128 @v_udiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: v_mov_b32_e32 v6, v5 ; GFX9-O0-NEXT: s_mov_b32 s14, s13 ; GFX9-O0-NEXT: v_xor_b32_e64 v6, v6, s14 -; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 killed $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: ; kill: def $sgpr12 killed $sgpr12 killed $sgpr12_sgpr13 ; GFX9-O0-NEXT: v_xor_b32_e64 v4, v4, s12 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec @@ -3232,10 +3216,10 @@ define i128 @v_udiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload ; GFX9-O0-NEXT: s_mov_b64 s[6:7], 1 ; GFX9-O0-NEXT: s_mov_b32 s5, s6 ; GFX9-O0-NEXT: s_waitcnt vmcnt(1) diff --git a/llvm/test/CodeGen/AMDGPU/rem_i128.ll b/llvm/test/CodeGen/AMDGPU/rem_i128.ll index ba9dd8f7c2468..6512bee36e88b 100644 --- a/llvm/test/CodeGen/AMDGPU/rem_i128.ll +++ b/llvm/test/CodeGen/AMDGPU/rem_i128.ll @@ -513,28 +513,21 @@ define i128 @v_srem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v5, v8 +; GFX9-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-O0-NEXT: s_nop 0 +; GFX9-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 def $vgpr7_vgpr8 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v8, v6 -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v8 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v7 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v5 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v4 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill ; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_mov_b64 s[8:9], s[6:7] -; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[8:9] +; GFX9-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[6:7] ; GFX9-O0-NEXT: s_mov_b64 s[12:13], 0x7f -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[12:13] -; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[14:15] +; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[12:13] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[14:15] -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[6:7] -; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[14:15] +; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[6:7] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[14:15] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, v6, v9, s[8:9] ; GFX9-O0-NEXT: v_and_b32_e64 v6, 1, v6 @@ -545,7 +538,6 @@ define i128 @v_srem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: v_mov_b32_e32 v6, v5 ; GFX9-O0-NEXT: s_mov_b32 s14, s13 ; GFX9-O0-NEXT: v_xor_b32_e64 v6, v6, s14 -; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 killed $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: ; kill: def $sgpr12 killed $sgpr12 killed $sgpr12_sgpr13 ; GFX9-O0-NEXT: v_xor_b32_e64 v4, v4, s12 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec @@ -1081,10 +1073,10 @@ define i128 @v_srem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload ; GFX9-O0-NEXT: s_mov_b64 s[6:7], 1 ; GFX9-O0-NEXT: s_mov_b32 s5, s6 ; GFX9-O0-NEXT: s_waitcnt vmcnt(1) @@ -1897,28 +1889,21 @@ define i128 @v_urem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v5, v8 +; GFX9-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-O0-NEXT: s_nop 0 +; GFX9-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; implicit-def: $sgpr8 ; GFX9-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 def $vgpr7_vgpr8 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v8, v6 -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v8 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v7 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill -; GFX9-O0-NEXT: v_mov_b32_e32 v10, v5 -; GFX9-O0-NEXT: v_mov_b32_e32 v9, v4 -; GFX9-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill ; GFX9-O0-NEXT: s_nop 0 -; GFX9-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill -; GFX9-O0-NEXT: s_mov_b64 s[8:9], s[6:7] -; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[8:9] +; GFX9-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[7:8], s[6:7] ; GFX9-O0-NEXT: s_mov_b64 s[12:13], 0x7f -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[12:13] -; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[14:15] +; GFX9-O0-NEXT: v_cmp_gt_u64_e64 s[14:15], v[4:5], s[12:13] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[14:15] -; GFX9-O0-NEXT: s_mov_b64 s[14:15], s[6:7] -; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[14:15] +; GFX9-O0-NEXT: v_cmp_ne_u64_e64 s[14:15], v[7:8], s[6:7] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[14:15] ; GFX9-O0-NEXT: v_cndmask_b32_e64 v6, v6, v9, s[8:9] ; GFX9-O0-NEXT: v_and_b32_e64 v6, 1, v6 @@ -1929,7 +1914,6 @@ define i128 @v_urem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: v_mov_b32_e32 v6, v5 ; GFX9-O0-NEXT: s_mov_b32 s14, s13 ; GFX9-O0-NEXT: v_xor_b32_e64 v6, v6, s14 -; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 killed $vgpr4_vgpr5 killed $exec ; GFX9-O0-NEXT: ; kill: def $sgpr12 killed $sgpr12 killed $sgpr12_sgpr13 ; GFX9-O0-NEXT: v_xor_b32_e64 v4, v4, s12 ; GFX9-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec @@ -2465,10 +2449,10 @@ define i128 @v_urem_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload ; GFX9-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload -; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload ; GFX9-O0-NEXT: s_mov_b64 s[6:7], 1 ; GFX9-O0-NEXT: s_mov_b32 s5, s6 ; GFX9-O0-NEXT: s_waitcnt vmcnt(1) diff --git a/llvm/test/CodeGen/AVR/cmp.ll b/llvm/test/CodeGen/AVR/cmp.ll index efc9b8da45ba5..c932bda1807f1 100644 --- a/llvm/test/CodeGen/AVR/cmp.ll +++ b/llvm/test/CodeGen/AVR/cmp.ll @@ -298,3 +298,18 @@ define i16 @cmp_i16_gt_1023(i16 %0) { %3 = zext i1 %2 to i16 ret i16 %3 } + +define void @cmp_issue152097(i16 %a) addrspace(1) { +; See: https://github.com/llvm/llvm-project/issues/152097 +; CHECK-LABEL: cmp_issue152097 +; CHECK: ldi r18, -1 +; CHECK-NEXT: cpi r24, -2 +; CHECK-NEXT: cpc r25, r18 +; CHECK-NEXT: ret + %cmp = icmp ugt i16 -2, %a + br i1 %cmp, label %if.then, label %if.else +if.then: + ret void +if.else: + ret void +} diff --git a/llvm/test/CodeGen/BPF/BTF/ptr-named-2.ll b/llvm/test/CodeGen/BPF/BTF/ptr-named-2.ll new file mode 100644 index 0000000000000..df0cbeb3dd625 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/ptr-named-2.ll @@ -0,0 +1,59 @@ +; RUN: llc -mtriple=bpfel -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; RUN: llc -mtriple=bpfeb -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; +; This IR is hand-written. + +; ModuleID = 'ptr-named-2.ll' +source_filename = "ptr-named-2.ll" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "bpfel-unknown-none" + +%struct.TypeExamples = type { i32*, i32, i32, i32* } + +@type_examples = internal global %struct.TypeExamples zeroinitializer, align 8, !dbg !0 + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!2, !3, !4} +!llvm.ident = !{!21} + +; CHECK-BTF: [1] STRUCT 'TypeExamples' size=32 vlen=4 +; CHECK-BTF-NEXT: 'ptr' type_id=2 bits_offset=0 +; CHECK-BTF-NEXT: 'volatile' type_id=4 bits_offset=64 +; CHECK-BTF-NEXT: 'const' type_id=5 bits_offset=128 +; CHECK-BTF-NEXT: 'restrict_ptr' type_id=6 bits_offset=192 +; CHECK-BTF-NEXT: [2] PTR '(anon)' type_id=3 +; CHECK-BTF-NEXT: [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED +; CHECK-BTF-NEXT: [4] VOLATILE '(anon)' type_id=3 +; CHECK-BTF-NEXT: [5] CONST '(anon)' type_id=3 +; CHECK-BTF-NEXT: [6] RESTRICT '(anon)' type_id=7 +; CHECK-BTF-NEXT: [7] PTR '(anon)' type_id=3 +; CHECK-BTF-NEXT: [8] VAR 'type_examples' type_id=1, linkage=static +; CHECK-BTF-NEXT: [9] DATASEC '.bss' size=0 vlen=1 +; CHECK-BTF-NEXT: type_id=8 offset=0 size=24 + +!0 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !6, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None) +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = distinct !DIGlobalVariable(name: "type_examples", scope: !1, file: !6, line: 12, type: !9, isLocal: true, isDefinition: true) +!6 = !DIFile(filename: "ptr-named-2.ll", directory: "/tmp") +!7 = !{} +!8 = !{!0} +!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TypeExamples", file: !6, line: 5, size: 256, elements: !10) +!10 = !{!11, !12, !13, !14} +!11 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !9, file: !6, line: 6, baseType: !15, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_member, name: "volatile", scope: !9, file: !6, line: 7, baseType: !17, size: 64, offset: 64) +!13 = !DIDerivedType(tag: DW_TAG_member, name: "const", scope: !9, file: !6, line: 8, baseType: !18, size: 64, offset: 128) +!14 = !DIDerivedType(tag: DW_TAG_member, name: "restrict_ptr", scope: !9, file: !6, line: 9, baseType: !19, size: 64, offset: 192) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*int", baseType: !16, size: 64) +!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!17 = !DIDerivedType(tag: DW_TAG_volatile_type, name: "volatile int", baseType: !16) +!18 = !DIDerivedType(tag: DW_TAG_const_type, name: "const int", baseType: !16) +!19 = !DIDerivedType(tag: DW_TAG_restrict_type, name: "*int restrict", baseType: !20) +!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64) +!21 = !{!"my hand-written IR"} diff --git a/llvm/test/CodeGen/BPF/BTF/ptr-named.ll b/llvm/test/CodeGen/BPF/BTF/ptr-named.ll new file mode 100644 index 0000000000000..675c34e976abb --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/ptr-named.ll @@ -0,0 +1,75 @@ +; RUN: llc -mtriple=bpfel -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; RUN: llc -mtriple=bpfeb -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; +; Source: +; #![no_std] +; #![no_main] +; +; pub struct MyType { +; ptr: *const u32, +; } +; +; impl MyType { +; pub const fn new() -> Self { +; let ptr = core::ptr::null(); +; Self { ptr } +; } +; } +; +; unsafe impl Sync for MyType {} +; +; #[unsafe(no_mangle)] +; pub static X: MyType = MyType::new(); +; +; #[cfg(not(test))] +; #[panic_handler] +; fn panic(_info: &core::panic::PanicInfo) -> ! { +; loop {} +; } +; Compilation flag: +; cargo +nightly rustc -Zbuild-std=core --target=bpfel-unknown-none -- --emit=llvm-bc +; llvm-extract --glob=X $(find target/ -name "*.bc" | head -n 1) -o ptr-named.bc +; llvm-dis ptr-named.bc -o ptr-named.ll + +; ModuleID = 'ptr-named.bc' +source_filename = "1m2uqe50qkwxmo53ydydvou91" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "bpfel" + +@X = constant [8 x i8] zeroinitializer, align 8, !dbg !0 + +!llvm.module.flags = !{!11, !12, !13, !14} +!llvm.ident = !{!15} +!llvm.dbg.cu = !{!16} + +; CHECK-BTF: [1] STRUCT 'MyType' size=8 vlen=1 +; CHECK-BTF-NEXT: 'ptr' type_id=2 bits_offset=0 +; CHECK-BTF-NEXT: [2] PTR '(anon)' type_id=3 +; CHECK-BTF-NEXT: [3] INT 'u32' size=4 bits_offset=0 nr_bits=32 encoding=(none) +; CHECK-BTF-NEXT: [4] VAR 'X' type_id=1, linkage=global +; CHECK-BTF-NEXT: [5] DATASEC '.rodata' size=0 vlen=1 +; CHECK-BTF-NEXT: type_id=4 offset=0 size=8 + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "X", scope: !2, file: !3, line: 19, type: !4, isLocal: false, isDefinition: true, align: 64) +!2 = !DINamespace(name: "ptr_named", scope: null) +!3 = !DIFile(filename: "ptr-named/src/main.rs", directory: "/tmp/ptr-named", checksumkind: CSK_MD5, checksum: "e37168304600b30cbb5ba168f0384932") +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyType", scope: !2, file: !5, size: 64, align: 64, flags: DIFlagPublic, elements: !6, templateParams: !10, identifier: "7609fa40332dd486922f074276a171c3") +!5 = !DIFile(filename: "", directory: "") +!6 = !{!7} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !4, file: !5, baseType: !8, size: 64, align: 64, flags: DIFlagPrivate) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const u32", baseType: !9, size: 64, align: 64, dwarfAddressSpace: 0) +!9 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) +!10 = !{} +!11 = !{i32 8, !"PIC Level", i32 2} +!12 = !{i32 7, !"PIE Level", i32 2} +!13 = !{i32 7, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{!"rustc version 1.92.0-nightly (c8905eaa6 2025-09-28)"} +!16 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !17, producer: "clang LLVM (rustc version 1.92.0-nightly (c8905eaa6 2025-09-28))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !18, splitDebugInlining: false, nameTableKind: None) +!17 = !DIFile(filename: "ptr-named/src/main.rs/@/1m2uqe50qkwxmo53ydydvou91", directory: "/tmp/ptr-named") +!18 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/variant-part.ll b/llvm/test/CodeGen/BPF/BTF/variant-part.ll new file mode 100644 index 0000000000000..1071e618f601b --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/variant-part.ll @@ -0,0 +1,87 @@ +; RUN: llc -mtriple=bpfel -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; RUN: llc -mtriple=bpfeb -filetype=obj -o %t1 %s +; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t1 +; RUN: %python %p/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s +; +; Source: +; #![no_std] +; #![no_main] +; +; pub enum MyEnum { +; First { a: u32, b: i32 }, +; Second(u32), +; } +; +; #[unsafe(no_mangle)] +; pub static X: MyEnum = MyEnum::First { a: 54, b: -23 }; +; +; #[cfg(not(test))] +; #[panic_handler] +; fn panic(_info: &core::panic::PanicInfo) -> ! { +; loop {} +; } +; Compilation flag: +; cargo +nightly rustc -Zbuild-std=core --target=bpfel-unknown-none -- --emit=llvm-bc +; llvm-extract --glob=X $(find target/ -name "*.bc" | head -n 1) -o variant-part.bc +; llvm-dis variant-part.bc -o variant-part.ll + +; ModuleID = 'variant-part.bc' +source_filename = "c0znihgkvro8hs0n88fgrtg6x" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "bpfel" + +@X = constant [12 x i8] c"\00\00\00\006\00\00\00\E9\FF\FF\FF", align 4, !dbg !0 + +!llvm.module.flags = !{!22, !23, !24, !25} +!llvm.ident = !{!26} +!llvm.dbg.cu = !{!27} + +; CHECK-BTF: [1] STRUCT 'MyEnum' size=12 vlen=1 +; CHECK-BTF-NEXT: '(anon)' type_id=3 bits_offset=0 +; CHECK-BTF-NEXT: [2] INT 'u32' size=4 bits_offset=0 nr_bits=32 encoding=(none) +; CHECK-BTF-NEXT: [3] UNION '(anon)' size=12 vlen=3 +; CHECK-BTF-NEXT: '(anon)' type_id=2 bits_offset=0 +; CHECK-BTF-NEXT: 'First' type_id=4 bits_offset=0 +; CHECK-BTF-NEXT: 'Second' type_id=6 bits_offset=0 +; CHECK-BTF-NEXT: [4] STRUCT 'First' size=12 vlen=2 +; CHECK-BTF-NEXT: 'a' type_id=2 bits_offset=32 +; CHECK-BTF-NEXT: 'b' type_id=5 bits_offset=64 +; CHECK-BTF-NEXT: [5] INT 'i32' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED +; CHECK-BTF-NEXT: [6] STRUCT 'Second' size=12 vlen=1 +; CHECK-BTF-NEXT: '__0' type_id=2 bits_offset=32 +; CHECK-BTF-NEXT: [7] VAR 'X' type_id=1, linkage=global +; CHECK-BTF-NEXT: [8] DATASEC '.rodata' size=0 vlen=1 +; CHECK-BTF-NEXT: type_id=7 offset=0 size=12 + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "X", scope: !2, file: !3, line: 10, type: !4, isLocal: false, isDefinition: true, align: 32) +!2 = !DINamespace(name: "variant_part", scope: null) +!3 = !DIFile(filename: "variant-part/src/main.rs", directory: "/tmp/variant-part", checksumkind: CSK_MD5, checksum: "b94cd53886ea8f14cbc116b36bc7dd36") +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyEnum", scope: !2, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !6, templateParams: !16, identifier: "faba668fd9f71e9b7cf3b9ac5e8b93cb") +!5 = !DIFile(filename: "", directory: "") +!6 = !{!7} +!7 = !DICompositeType(tag: DW_TAG_variant_part, scope: !4, file: !5, size: 96, align: 32, elements: !8, templateParams: !16, identifier: "e4aee046fc86d111657622fdcb8c42f7", discriminator: !21) +!8 = !{!9, !17} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "First", scope: !7, file: !5, baseType: !10, size: 96, align: 32, extraData: i32 0) +!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "First", scope: !4, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !11, templateParams: !16, identifier: "cc7748c842e275452db4205b190c8ff7") +!11 = !{!12, !14} +!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !5, baseType: !13, size: 32, align: 32, offset: 32, flags: DIFlagPublic) +!13 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) +!14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !5, baseType: !15, size: 32, align: 32, offset: 64, flags: DIFlagPublic) +!15 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) +!16 = !{} +!17 = !DIDerivedType(tag: DW_TAG_member, name: "Second", scope: !7, file: !5, baseType: !18, size: 96, align: 32, extraData: i32 1) +!18 = !DICompositeType(tag: DW_TAG_structure_type, name: "Second", scope: !4, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !19, templateParams: !16, identifier: "a2094b1381f3082d504fbd0903aa7c06") +!19 = !{!20} +!20 = !DIDerivedType(tag: DW_TAG_member, name: "__0", scope: !18, file: !5, baseType: !13, size: 32, align: 32, offset: 32, flags: DIFlagPublic) +!21 = !DIDerivedType(tag: DW_TAG_member, scope: !4, file: !5, baseType: !13, size: 32, align: 32, flags: DIFlagArtificial) +!22 = !{i32 8, !"PIC Level", i32 2} +!23 = !{i32 7, !"PIE Level", i32 2} +!24 = !{i32 7, !"Dwarf Version", i32 4} +!25 = !{i32 2, !"Debug Info Version", i32 3} +!26 = !{!"rustc version 1.91.0-nightly (160e7623e 2025-08-26)"} +!27 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !28, producer: "clang LLVM (rustc version 1.91.0-nightly (160e7623e 2025-08-26))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !29, splitDebugInlining: false, nameTableKind: None) +!28 = !DIFile(filename: "variant-part/src/main.rs/@/c0znihgkvro8hs0n88fgrtg6x", directory: "/tmp/variant-part") +!29 = !{!0} diff --git a/llvm/test/CodeGen/Hexagon/hexagon-strcpy.ll b/llvm/test/CodeGen/Hexagon/hexagon-strcpy.ll index b23366bc11aca..f5430dfea5865 100644 --- a/llvm/test/CodeGen/Hexagon/hexagon-strcpy.ll +++ b/llvm/test/CodeGen/Hexagon/hexagon-strcpy.ll @@ -1,20 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=hexagon -verify-machineinstrs < %s | FileCheck %s @.str = private unnamed_addr constant [31 x i8] c"DHRYSTONE PROGRAM, 3'RD STRING\00", align 1 @.str1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 -; Function Attrs: nounwind declare i32 @printf(i8* nocapture readonly, ...) ; Function Attrs: nounwind -define i32 @main() { +define i32 @main() nounwind { ; CHECK-LABEL: main: -; CHECK: .cfi_startproc -; CHECK-NEXT: // %bb.0: // %entry -; CHECK-NEXT: .cfi_def_cfa r30, 8 -; CHECK-NEXT: .cfi_offset r31, -4 -; CHECK-NEXT: .cfi_offset r30, -8 +; CHECK: // %bb.0: // %entry ; CHECK-NEXT: { ; CHECK-NEXT: r0 = ##.L.str1 ; CHECK-NEXT: r3:2 = CONST64(#2325073635944967245) @@ -53,5 +48,4 @@ entry: ret i32 0 } -; Function Attrs: nounwind declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) diff --git a/llvm/test/CodeGen/Hexagon/insert-big.ll b/llvm/test/CodeGen/Hexagon/insert-big.ll new file mode 100644 index 0000000000000..8735a6679bf54 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/insert-big.ll @@ -0,0 +1,47 @@ +; Check that llc does not abort, which happened due to incorrect MIR. +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=1 < %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=2 < %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=3 < %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=4 < %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=5 < %s + +; Look for this symptom, in case llc does not check invalid IR. +; CHECK-NOT: insert(%14,%5,#5,#5) + +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=1 -debug-only=hexinsert -stop-after hexinsert < %s 2>&1 | FileCheck %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=2 -debug-only=hexinsert -stop-after hexinsert < %s 2>&1 | FileCheck %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=3 -debug-only=hexinsert -stop-after hexinsert < %s 2>&1 | FileCheck %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=4 -debug-only=hexinsert -stop-after hexinsert < %s 2>&1 | FileCheck %s +; RUN: llc -O2 -mtriple=hexagon -insert-max-ifmap=5 -debug-only=hexinsert -stop-after hexinsert < %s 2>&1 | FileCheck %s + +; REQUIRES: asserts + +define i32 @f(i32 %0, i32 %1, i32 %2) { +entry: + switch i32 %0, label %common.ret1 [ + i32 8907, label %3 + i32 4115, label %6 + ] + +common.ret1: + %common.ret1.op = phi i32 [ %5, %3 ], [ %526, %6 ], [ 0, %entry ] + ret i32 %common.ret1.op + +3: + %4 = shl i32 %2, 5 + %5 = and i32 %4, 992 + br label %common.ret1 + +6: + %7 = shl i32 %0, 10 + %8 = and i32 %7, 7168 + %9 = shl i32 %0, 5 + %10 = and i32 %9, 992 + %11 = or i32 %10, %8 + %12 = and i32 %0, 1 + %13 = or i32 %11, %12 + %14 = shl i32 %1, 1 + %15 = and i32 %14, 2031616 + %526 = or i32 %13, %15 + br label %common.ret1 +} diff --git a/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll b/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll new file mode 100644 index 0000000000000..8b121c539229d --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/inst_setcc_uno_uo.ll @@ -0,0 +1,93 @@ +;; RUN: llc --mtriple=hexagon -mattr=+hvxv79,+hvx-length128b %s -o - | FileCheck %s + +define dso_local void @store_isnan_f32(ptr %a, ptr %b, ptr %isnan_cmp) local_unnamed_addr { +entry: + %arrayidx_a = getelementptr inbounds nuw float, ptr %a, i32 0 + %arrayidx_b = getelementptr inbounds nuw float, ptr %b, i32 0 + %0 = load <32 x float>, ptr %arrayidx_a, align 4 + %1 = load <32 x float>, ptr %arrayidx_b, align 4 + %.vectorized = fcmp uno <32 x float> %0, %1 + %.LS.instance = zext <32 x i1> %.vectorized to <32 x i32> + %arrayidx1 = getelementptr inbounds nuw i32, ptr %isnan_cmp, i32 0 + store <32 x i32> %.LS.instance, ptr %arrayidx1, align 4 + ret void +} + +; CHECK: store_isnan_f32 +; CHECK: [[RONE32:r[0-9]+]] = #1 +; CHECK: [[VOP2_F32:v[0-9]+]] = vxor([[VOP2_F32]],[[VOP2_F32]]) +; CHECK: [[VOP1_F32:v[0-9]+]] = vmemu(r0+#0) +; CHECK: [[VONES32:v[0-9]+]] = vsplat([[RONE32]]) +; CHECK: [[Q1_F32:q[0-9]+]] = vcmp.eq([[VOP1_F32]].w,[[VOP1_F32]].w) +; CHECK: [[VOP3_F32:v[0-9]+]] = vmemu(r1+#0) +; CHECK: [[Q1_F32]] &= vcmp.eq([[VOP3_F32]].w,[[VOP3_F32]].w) +; CHECK: [[VOUT_F32:v[0-9]+]] = vmux([[Q1_F32]],[[VOP2_F32]],[[VONES32]]) +; CHECK: vmemu(r2+#0) = [[VOUT_F32]] + +define dso_local void @store_isnan_f16(ptr %a, ptr %b, ptr %isnan_cmp) local_unnamed_addr { +entry: + %arrayidx_a = getelementptr inbounds nuw half, ptr %a, i32 0 + %arrayidx_b = getelementptr inbounds nuw half, ptr %b, i32 0 + %0 = load <64 x half>, ptr %arrayidx_a, align 2 + %1 = load <64 x half>, ptr %arrayidx_b, align 2 + %.vectorized = fcmp uno <64 x half> %0, %1 + %conv.LS.instance = zext <64 x i1> %.vectorized to <64 x i16> + %arrayidx1 = getelementptr inbounds nuw i16, ptr %isnan_cmp, i32 0 + store <64 x i16> %conv.LS.instance, ptr %arrayidx1, align 2 + ret void +} +; CHECK-LABEL: store_isnan_f16 +; CHECK: [[RONE16:r[0-9]+]] = #1 +; CHECK: [[VOP2_F16:v[0-9]+]] = vxor([[VOP2_F16]],[[VOP2_F16]]) +; CHECK: [[VOP1_F16:v[0-9]+]] = vmemu(r0+#0) +; CHECK: [[VONES16:v[0-9]+]].h = vsplat([[RONE16]]) +; CHECK: [[Q1_F16:q[0-9]+]] = vcmp.eq([[VOP1_F16]].h,[[VOP1_F16]].h) +; CHECK: [[VOP3_F16:v[0-9]+]] = vmemu(r1+#0) +; CHECK: [[Q1_F16]] &= vcmp.eq([[VOP3_F16]].h,[[VOP3_F16]].h) +; CHECK: [[VOUT_F16:v[0-9]+]] = vmux([[Q1_F16]],[[VOP2_F16]],[[VONES16]]) +; CHECK: vmemu(r2+#0) = [[VOUT_F32]] + +define dso_local void @store_isordered_f32(ptr %a, ptr %b, ptr %isordered_cmp) local_unnamed_addr { +entry: + %arrayidx_a = getelementptr inbounds nuw float, ptr %a, i32 0 + %arrayidx_b = getelementptr inbounds nuw float, ptr %b, i32 0 + %0 = load <32 x float>, ptr %arrayidx_a, align 4 + %1 = load <32 x float>, ptr %arrayidx_b, align 4 + %.vectorized = fcmp ord <32 x float> %0, %1 + %.LS.instance = zext <32 x i1> %.vectorized to <32 x i32> + %arrayidx1 = getelementptr inbounds nuw i32, ptr %isordered_cmp, i32 0 + store <32 x i32> %.LS.instance, ptr %arrayidx1, align 4 + ret void +} +; CHECK-LABEL: store_isordered_f32 +; CHECK: [[VOP2_ORD_F32:v[0-9]+]] = vxor([[VOP2_ORD_F32]],[[VOP2_ORD_F32]]) +; CHECK: [[VOP1_ORD_F32:v[0-9]+]] = vmemu(r0+#0) +; CHECK: [[VONES_ORD_F32:v[0-9]+]] = vsplat([[RONE32]]) +; CHECK: [[Q1_ORD_F32:q[0-9]+]] = vcmp.eq([[VOP1_ORD_F32]].w,[[VOP1_ORD_F32]].w) +; CHECK: [[VOP3_ORD_F32:v[0-9]+]] = vmemu(r1+#0) +; CHECK: [[Q1_ORD_F32]] &= vcmp.eq([[VOP3_ORD_F32]].w,[[VOP3_ORD_F32]].w) +; CHECK: [[VOUT_ORD_F32:v[0-9]+]] = vmux([[Q1_ORD_F32]],[[VONES_ORD_F32]],[[VOP2_ORD_F32]]) +; CHECK: vmemu(r2+#0) = [[VOUT_ORD_F32]] + + +define dso_local void @store_isordered_f16(ptr %a, ptr %b, ptr %isordered_cmp) local_unnamed_addr { +entry: + %arrayidx_a = getelementptr inbounds nuw half, ptr %a, i32 0 + %arrayidx_b = getelementptr inbounds nuw half, ptr %b, i32 0 + %0 = load <64 x half>, ptr %arrayidx_a, align 2 + %1 = load <64 x half>, ptr %arrayidx_b, align 2 + %.vectorized = fcmp ord <64 x half> %0, %1 + %conv.LS.instance = zext <64 x i1> %.vectorized to <64 x i16> + %arrayidx1 = getelementptr inbounds nuw i16, ptr %isordered_cmp, i32 0 + store <64 x i16> %conv.LS.instance, ptr %arrayidx1, align 2 + ret void +} +; CHECK-LABEL: store_isordered_f16 +; CHECK: [[VOP2_ORD_F16:v[0-9]+]] = vxor([[VOP2_ORD_F16]],[[VOP2_ORD_F16]]) +; CHECK: [[VOP1_ORD_F16:v[0-9]+]] = vmemu(r0+#0) +; CHECK: [[VONES_ORD_F16:v[0-9]+]].h = vsplat([[RONE16]]) +; CHECK: [[Q1_ORD_F16:q[0-9]+]] = vcmp.eq([[VOP1_ORD_F16]].h,[[VOP1_ORD_F16]].h) +; CHECK: [[VOP3_ORD_F16:v[0-9]+]] = vmemu(r1+#0) +; CHECK: [[Q1_ORD_F16]] &= vcmp.eq([[VOP3_ORD_F16]].h,[[VOP3_ORD_F16]].h) +; CHECK: [[VOUT_ORD_F16:v[0-9]+]] = vmux([[Q1_ORD_F16]],[[VONES_ORD_F16]],[[VOP2_ORD_F16]]) +; CHECK: vmemu(r2+#0) = [[VOUT_ORD_F16]] diff --git a/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll b/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll new file mode 100644 index 0000000000000..ff50f1abe5897 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll @@ -0,0 +1,38 @@ +; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s + +; CHECK-NOT: r{{[0-9]+}} = asr(r{{[0-9]+}},#{{[0-9]+}}) +; CHECK-NOT: r{{[0-9]+}}:{{[0-9]+}} = mpyu(r{{[0-9]+}},r{{[0-9]+}}) +; CHECK-NOT: r{{[0-9]+}} += mpyi(r{{[0-9]+}},r{{[0-9]+}}) +; CHECK: r{{[0-9]+}}:{{[0-9]+}} = mpy(r{{[0-9]+}},r{{[0-9]+}}) + +; ModuleID = '39544.c' +source_filename = "39544.c" +target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" +target triple = "hexagon" + +define dso_local void @mul_n(i64* nocapture %p, i32* nocapture readonly %a, i32 %k, i32 %n) local_unnamed_addr { +entry: + %cmp7 = icmp sgt i32 %n, 0 + br i1 %cmp7, label %for.body.lr.ph, label %for.cond.cleanup + +for.body.lr.ph: ; preds = %entry + %conv1 = sext i32 %k to i64 + br label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + ret void + +for.body: ; preds = %for.body, %for.body.lr.ph + %arrayidx.phi = phi i32* [ %a, %for.body.lr.ph ], [ %arrayidx.inc, %for.body ] + %arrayidx2.phi = phi i64* [ %p, %for.body.lr.ph ], [ %arrayidx2.inc, %for.body ] + %i.08 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] + %0 = load i32, i32* %arrayidx.phi, align 4 + %conv = sext i32 %0 to i64 + %mul = mul nsw i64 %conv, %conv1 + store i64 %mul, i64* %arrayidx2.phi, align 8 + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + %arrayidx.inc = getelementptr i32, i32* %arrayidx.phi, i32 1 + %arrayidx2.inc = getelementptr i64, i64* %arrayidx2.phi, i32 1 + br i1 %exitcond, label %for.cond.cleanup, label %for.body +} diff --git a/llvm/test/CodeGen/Hexagon/swp-load-to-store-forward.mir b/llvm/test/CodeGen/Hexagon/swp-load-to-store-forward.mir new file mode 100644 index 0000000000000..2960343564fca --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/swp-load-to-store-forward.mir @@ -0,0 +1,50 @@ +# RUN: llc -mtriple=hexagon -run-pass pipeliner %s -o /dev/null + +# Check that edges that violate topological order are not added to the +# SwingSchedulerDAG. This is a case where the crash was caused by PR 145878. + +--- | + target triple = "hexagon" + + define void @crash_145878() { + entry: + br label %loop + + loop: ; preds = %loop, %entry + %lsr.iv2 = phi i32 [ %lsr.iv.next, %loop ], [ 1, %entry ] + %lsr.iv = phi ptr [ %cgep3, %loop ], [ inttoptr (i32 -8 to ptr), %entry ] + %cgep = getelementptr i8, ptr %lsr.iv, i32 12 + %load = load i32, ptr %cgep, align 4 + store i32 %load, ptr %lsr.iv, align 4 + %lsr.iv.next = add nsw i32 %lsr.iv2, -1 + %iv.cmp.not = icmp eq i32 %lsr.iv.next, 0 + %cgep3 = getelementptr i8, ptr %lsr.iv, i32 -8 + br i1 %iv.cmp.not, label %exit, label %loop + + exit: ; preds = %loop + ret void + } +... +--- +name: crash_145878 +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1(0x80000000) + + %5:intregs = A2_tfrsi -8 + J2_loop0i %bb.1, 1, implicit-def $lc0, implicit-def $sa0, implicit-def $usr + + bb.1.loop (machine-block-address-taken): + successors: %bb.2(0x04000000), %bb.1(0x7c000000) + + %1:intregs = PHI %5, %bb.0, %3, %bb.1 + %6:intregs = L2_loadri_io %1, 12 :: (load (s32) from %ir.cgep) + S2_storeri_io %1, 0, killed %6 :: (store (s32) into %ir.lsr.iv) + %3:intregs = A2_addi %1, -8 + ENDLOOP0 %bb.1, implicit-def $pc, implicit-def $lc0, implicit $sa0, implicit $lc0 + J2_jump %bb.2, implicit-def dead $pc + + bb.2.exit: + PS_jmpret $r31, implicit-def dead $pc +... diff --git a/llvm/test/CodeGen/Hexagon/swp-many-stores.mir b/llvm/test/CodeGen/Hexagon/swp-many-stores.mir new file mode 100644 index 0000000000000..bf14dcf3c4fb3 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/swp-many-stores.mir @@ -0,0 +1,88 @@ +# RUN: llc -run-pass pipeliner -debug-only=pipeliner %s -o /dev/null -pipeliner-max-num-stores=5 2>&1 | FileCheck %s +# REQUIRES: asserts + +# This loop has six stores, which exceeds the limit set by +# `pipeliner-max-num-stores`. + +# CHECK: Too many stores + +--- | + target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" + target triple = "hexagon-unknown-linux-musl" + + define void @f(ptr %a, i32 %n) #0 { + entry: + %guard = icmp sgt i32 %n, 0 + %btc = sub nsw i32 %n, 1 + br i1 %guard, label %loop.preheader, label %exit + + loop.preheader: ; preds = %entry + %0 = add i32 %n, 1 + %cgep = getelementptr i8, ptr %a, i32 %0 + br label %loop + + loop: ; preds = %loop.preheader, %loop + %lsr.iv = phi ptr [ %cgep, %loop.preheader ], [ %cgep8, %loop ] + %i = phi i32 [ %i.dec, %loop ], [ %btc, %loop.preheader ] + %cgep7 = getelementptr i8, ptr %lsr.iv, i32 -2 + store i8 0, ptr %cgep7, align 1 + %cgep8 = getelementptr i8, ptr %lsr.iv, i32 -1 + store i8 1, ptr %cgep8, align 1 + store i8 2, ptr %lsr.iv, align 1 + %cgep9 = getelementptr i8, ptr %lsr.iv, i32 1 + store i8 3, ptr %cgep9, align 1 + %cgep10 = getelementptr i8, ptr %lsr.iv, i32 2 + store i8 4, ptr %cgep10, align 1 + %cgep11 = getelementptr i8, ptr %lsr.iv, i32 3 + store i8 5, ptr %cgep11, align 1 + %i.dec = sub i32 %i, 1 + %ec = icmp eq i32 %i.dec, 0 + br i1 %ec, label %exit, label %loop + + exit: ; preds = %loop, %entry + ret void + } + + attributes #0 = { "target-cpu"="hexagonv79" } +... +--- +name: f +tracksRegLiveness: true +body: | + bb.0.entry: + successors: %bb.1(0x50000000), %bb.3(0x30000000) + liveins: $r0, $r1 + + %7:intregs = COPY $r1 + %6:intregs = COPY $r0 + %8:predregs = C2_cmpgti %7, 0 + J2_jumpf %8, %bb.3, implicit-def dead $pc + J2_jump %bb.1, implicit-def dead $pc + + bb.1.loop.preheader: + successors: %bb.2(0x80000000) + + %0:intregs = A2_addi %7, -1 + %1:intregs = S4_addaddi %7, %6, 1 + %10:intregs = A2_tfrsi 0 + %11:intregs = A2_tfrsi 1 + %14:intregs = COPY %0 + J2_loop0r %bb.2, %14, implicit-def $lc0, implicit-def $sa0, implicit-def $usr + + bb.2.loop (machine-block-address-taken): + successors: %bb.3(0x04000000), %bb.2(0x7c000000) + + %2:intregs = PHI %1, %bb.1, %4, %bb.2 + S2_storerb_io %2, -2, %10 :: (store (s8) into %ir.cgep7) + %4:intregs = A2_addi %2, -1 + S2_storerb_io %2, -1, %11 :: (store (s8) into %ir.cgep8) + S4_storeirb_io %2, 0, 2 :: (store (s8) into %ir.lsr.iv) + S4_storeirb_io %2, 1, 3 :: (store (s8) into %ir.cgep9) + S4_storeirb_io %2, 2, 4 :: (store (s8) into %ir.cgep10) + S4_storeirb_io %2, 3, 5 :: (store (s8) into %ir.cgep11) + ENDLOOP0 %bb.2, implicit-def $pc, implicit-def $lc0, implicit $sa0, implicit $lc0 + J2_jump %bb.3, implicit-def dead $pc + + bb.3.exit: + PS_jmpret $r31, implicit-def dead $pc +... diff --git a/llvm/test/CodeGen/Hexagon/unaligned-vec-store.ll b/llvm/test/CodeGen/Hexagon/unaligned-vec-store.ll new file mode 100644 index 0000000000000..267e365243711 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/unaligned-vec-store.ll @@ -0,0 +1,23 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv68 -mattr=+hvxv68,+hvx-length128B < %s | FileCheck %s +; REQUIRES: asserts + +; Check that the test does not assert when unaligned vector store V6_vS32Ub_npred_ai is generated. +; CHECK: if (!p{{[0-3]}}) vmemu + +target triple = "hexagon-unknown-unknown-elf" + +define fastcc void @test(i1 %cmp.i.i) { +entry: + %call.i.i.i172 = load ptr, ptr null, align 4 + %add.ptr = getelementptr i8, ptr %call.i.i.i172, i32 1 + store <32 x i32> zeroinitializer, ptr %add.ptr, align 128 + %add.ptr4.i4 = getelementptr i8, ptr %call.i.i.i172, i32 129 + br i1 %cmp.i.i, label %common.ret, label %if.end.i.i + +common.ret: ; preds = %if.end.i.i, %entry + ret void + +if.end.i.i: ; preds = %entry + store <32 x i32> zeroinitializer, ptr %add.ptr4.i4, align 1 + br label %common.ret +} diff --git a/llvm/test/CodeGen/LoongArch/calling-conv-common.ll b/llvm/test/CodeGen/LoongArch/calling-conv-common.ll index d07e2914c753a..f7653af1fa9ba 100644 --- a/llvm/test/CodeGen/LoongArch/calling-conv-common.ll +++ b/llvm/test/CodeGen/LoongArch/calling-conv-common.ll @@ -122,23 +122,23 @@ define i64 @callee_large_scalars(i256 %a, i256 %b) nounwind { define i64 @caller_large_scalars() nounwind { ; CHECK-LABEL: caller_large_scalars: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -80 -; CHECK-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill -; CHECK-NEXT: st.d $zero, $sp, 24 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $zero, $sp, 40 ; CHECK-NEXT: vrepli.b $vr0, 0 -; CHECK-NEXT: vst $vr0, $sp, 8 +; CHECK-NEXT: vst $vr0, $sp, 24 ; CHECK-NEXT: ori $a0, $zero, 2 -; CHECK-NEXT: st.d $a0, $sp, 0 -; CHECK-NEXT: st.d $zero, $sp, 56 -; CHECK-NEXT: vst $vr0, $sp, 40 +; CHECK-NEXT: st.d $a0, $sp, 16 +; CHECK-NEXT: st.d $zero, $sp, 72 +; CHECK-NEXT: vst $vr0, $sp, 56 ; CHECK-NEXT: ori $a2, $zero, 1 -; CHECK-NEXT: addi.d $a0, $sp, 32 -; CHECK-NEXT: addi.d $a1, $sp, 0 -; CHECK-NEXT: st.d $a2, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 48 +; CHECK-NEXT: addi.d $a1, $sp, 16 +; CHECK-NEXT: st.d $a2, $sp, 48 ; CHECK-NEXT: pcaddu18i $ra, %call36(callee_large_scalars) ; CHECK-NEXT: jirl $ra, $ra, 0 -; CHECK-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 80 +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %1 = call i64 @callee_large_scalars(i256 1, i256 2) ret i64 %1 @@ -177,20 +177,20 @@ define i64 @callee_large_scalars_exhausted_regs(i64 %a, i64 %b, i64 %c, i64 %d, define i64 @caller_large_scalars_exhausted_regs() nounwind { ; CHECK-LABEL: caller_large_scalars_exhausted_regs: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -96 -; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $a0, $sp, 16 +; CHECK-NEXT: addi.d $sp, $sp, -112 +; CHECK-NEXT: st.d $ra, $sp, 104 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: st.d $a0, $sp, 8 ; CHECK-NEXT: ori $a0, $zero, 9 ; CHECK-NEXT: st.d $a0, $sp, 0 -; CHECK-NEXT: st.d $zero, $sp, 40 +; CHECK-NEXT: st.d $zero, $sp, 56 ; CHECK-NEXT: vrepli.b $vr0, 0 -; CHECK-NEXT: vst $vr0, $sp, 24 +; CHECK-NEXT: vst $vr0, $sp, 40 ; CHECK-NEXT: ori $a0, $zero, 10 -; CHECK-NEXT: st.d $a0, $sp, 16 -; CHECK-NEXT: st.d $zero, $sp, 72 +; CHECK-NEXT: st.d $a0, $sp, 32 +; CHECK-NEXT: st.d $zero, $sp, 88 ; CHECK-NEXT: ori $a0, $zero, 8 -; CHECK-NEXT: st.d $a0, $sp, 48 +; CHECK-NEXT: st.d $a0, $sp, 64 ; CHECK-NEXT: ori $a0, $zero, 1 ; CHECK-NEXT: ori $a1, $zero, 2 ; CHECK-NEXT: ori $a2, $zero, 3 @@ -198,12 +198,12 @@ define i64 @caller_large_scalars_exhausted_regs() nounwind { ; CHECK-NEXT: ori $a4, $zero, 5 ; CHECK-NEXT: ori $a5, $zero, 6 ; CHECK-NEXT: ori $a6, $zero, 7 -; CHECK-NEXT: addi.d $a7, $sp, 48 -; CHECK-NEXT: vst $vr0, $sp, 56 +; CHECK-NEXT: addi.d $a7, $sp, 64 +; CHECK-NEXT: vst $vr0, $sp, 72 ; CHECK-NEXT: pcaddu18i $ra, %call36(callee_large_scalars_exhausted_regs) ; CHECK-NEXT: jirl $ra, $ra, 0 -; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 96 +; CHECK-NEXT: ld.d $ra, $sp, 104 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 112 ; CHECK-NEXT: ret %1 = call i64 @callee_large_scalars_exhausted_regs( i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i256 8, i64 9, diff --git a/llvm/test/CodeGen/LoongArch/calling-conv-half.ll b/llvm/test/CodeGen/LoongArch/calling-conv-half.ll index c88b67f13d1e7..da8c3e93f6842 100644 --- a/llvm/test/CodeGen/LoongArch/calling-conv-half.ll +++ b/llvm/test/CodeGen/LoongArch/calling-conv-half.ll @@ -1252,8 +1252,8 @@ define i32 @caller_half_on_stack() nounwind { ; ; LA64F-LP64S-LABEL: caller_half_on_stack: ; LA64F-LP64S: # %bb.0: -; LA64F-LP64S-NEXT: addi.d $sp, $sp, -80 -; LA64F-LP64S-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill +; LA64F-LP64S-NEXT: addi.d $sp, $sp, -96 +; LA64F-LP64S-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill ; LA64F-LP64S-NEXT: lu12i.w $a0, -12 ; LA64F-LP64S-NEXT: ori $a1, $a0, 3200 ; LA64F-LP64S-NEXT: lu32i.d $a1, 0 @@ -1292,8 +1292,8 @@ define i32 @caller_half_on_stack() nounwind { ; LA64F-LP64S-NEXT: st.w $t0, $sp, 0 ; LA64F-LP64S-NEXT: pcaddu18i $ra, %call36(callee_half_on_stack) ; LA64F-LP64S-NEXT: jirl $ra, $ra, 0 -; LA64F-LP64S-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; LA64F-LP64S-NEXT: addi.d $sp, $sp, 80 +; LA64F-LP64S-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; LA64F-LP64S-NEXT: addi.d $sp, $sp, 96 ; LA64F-LP64S-NEXT: ret ; ; LA64F-LP64D-LABEL: caller_half_on_stack: @@ -1336,8 +1336,8 @@ define i32 @caller_half_on_stack() nounwind { ; ; LA64D-LP64S-LABEL: caller_half_on_stack: ; LA64D-LP64S: # %bb.0: -; LA64D-LP64S-NEXT: addi.d $sp, $sp, -80 -; LA64D-LP64S-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill +; LA64D-LP64S-NEXT: addi.d $sp, $sp, -96 +; LA64D-LP64S-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill ; LA64D-LP64S-NEXT: lu12i.w $a0, -12 ; LA64D-LP64S-NEXT: ori $a1, $a0, 3200 ; LA64D-LP64S-NEXT: lu32i.d $a1, 0 @@ -1376,8 +1376,8 @@ define i32 @caller_half_on_stack() nounwind { ; LA64D-LP64S-NEXT: st.w $t0, $sp, 0 ; LA64D-LP64S-NEXT: pcaddu18i $ra, %call36(callee_half_on_stack) ; LA64D-LP64S-NEXT: jirl $ra, $ra, 0 -; LA64D-LP64S-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; LA64D-LP64S-NEXT: addi.d $sp, $sp, 80 +; LA64D-LP64S-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; LA64D-LP64S-NEXT: addi.d $sp, $sp, 96 ; LA64D-LP64S-NEXT: ret ; ; LA64D-LP64D-LABEL: caller_half_on_stack: diff --git a/llvm/test/CodeGen/LoongArch/can-not-realign-stack.ll b/llvm/test/CodeGen/LoongArch/can-not-realign-stack.ll index 52d8dd05aaa4c..1a9de3b0ef3d1 100644 --- a/llvm/test/CodeGen/LoongArch/can-not-realign-stack.ll +++ b/llvm/test/CodeGen/LoongArch/can-not-realign-stack.ll @@ -14,41 +14,41 @@ define dso_local noundef signext i32 @main() nounwind { ; CHECK-LABEL: main: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -272 -; CHECK-NEXT: st.d $ra, $sp, 264 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $sp, $sp, -288 +; CHECK-NEXT: st.d $ra, $sp, 280 # 8-byte Folded Spill ; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_0) ; CHECK-NEXT: xvld $xr0, $a0, %pc_lo12(.LCPI0_0) -; CHECK-NEXT: xvst $xr0, $sp, 96 # 32-byte Folded Spill +; CHECK-NEXT: xvst $xr0, $sp, 112 # 32-byte Folded Spill ; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_1) ; CHECK-NEXT: xvld $xr1, $a0, %pc_lo12(.LCPI0_1) -; CHECK-NEXT: xvst $xr1, $sp, 64 # 32-byte Folded Spill +; CHECK-NEXT: xvst $xr1, $sp, 80 # 32-byte Folded Spill ; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_2) ; CHECK-NEXT: xvld $xr2, $a0, %pc_lo12(.LCPI0_2) -; CHECK-NEXT: xvst $xr2, $sp, 32 # 32-byte Folded Spill +; CHECK-NEXT: xvst $xr2, $sp, 48 # 32-byte Folded Spill ; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_3) ; CHECK-NEXT: xvld $xr3, $a0, %pc_lo12(.LCPI0_3) -; CHECK-NEXT: xvst $xr3, $sp, 0 # 32-byte Folded Spill -; CHECK-NEXT: xvst $xr0, $sp, 136 -; CHECK-NEXT: xvst $xr1, $sp, 168 -; CHECK-NEXT: xvst $xr2, $sp, 200 -; CHECK-NEXT: xvst $xr3, $sp, 232 -; CHECK-NEXT: addi.d $a0, $sp, 136 +; CHECK-NEXT: xvst $xr3, $sp, 16 # 32-byte Folded Spill +; CHECK-NEXT: xvst $xr0, $sp, 152 +; CHECK-NEXT: xvst $xr1, $sp, 184 +; CHECK-NEXT: xvst $xr2, $sp, 216 +; CHECK-NEXT: xvst $xr3, $sp, 248 +; CHECK-NEXT: addi.d $a0, $sp, 152 ; CHECK-NEXT: pcaddu18i $ra, %call36(foo) ; CHECK-NEXT: jirl $ra, $ra, 0 -; CHECK-NEXT: xvld $xr0, $sp, 96 # 32-byte Folded Reload -; CHECK-NEXT: xvst $xr0, $sp, 136 -; CHECK-NEXT: xvld $xr0, $sp, 64 # 32-byte Folded Reload -; CHECK-NEXT: xvst $xr0, $sp, 168 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload -; CHECK-NEXT: xvst $xr0, $sp, 200 -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload -; CHECK-NEXT: xvst $xr0, $sp, 232 -; CHECK-NEXT: addi.d $a0, $sp, 136 +; CHECK-NEXT: xvld $xr0, $sp, 112 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 152 +; CHECK-NEXT: xvld $xr0, $sp, 80 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 184 +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 216 +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 248 +; CHECK-NEXT: addi.d $a0, $sp, 152 ; CHECK-NEXT: pcaddu18i $ra, %call36(bar) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: move $a0, $zero -; CHECK-NEXT: ld.d $ra, $sp, 264 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 272 +; CHECK-NEXT: ld.d $ra, $sp, 280 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 288 ; CHECK-NEXT: ret entry: %s = alloca %struct.S, align 2 diff --git a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll index ccc5c703e71ed..15ac95dfc6c55 100644 --- a/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll +++ b/llvm/test/CodeGen/LoongArch/emergency-spill-slot.ll @@ -28,12 +28,12 @@ define void @func() { ; CHECK-NEXT: ld.w $a3, $a1, 0 ; CHECK-NEXT: ld.w $a2, $a1, 0 ; CHECK-NEXT: ld.w $a0, $a1, 0 -; CHECK-NEXT: st.d $fp, $sp, 0 +; CHECK-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill ; CHECK-NEXT: lu12i.w $fp, 1 ; CHECK-NEXT: ori $fp, $fp, 12 ; CHECK-NEXT: add.d $fp, $sp, $fp ; CHECK-NEXT: st.w $t8, $fp, 0 -; CHECK-NEXT: ld.d $fp, $sp, 0 +; CHECK-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload ; CHECK-NEXT: st.w $t8, $a1, 0 ; CHECK-NEXT: st.w $t7, $a1, 0 ; CHECK-NEXT: st.w $t6, $a1, 0 diff --git a/llvm/test/CodeGen/LoongArch/frame.ll b/llvm/test/CodeGen/LoongArch/frame.ll index 048703029d8c6..b29d8634854f3 100644 --- a/llvm/test/CodeGen/LoongArch/frame.ll +++ b/llvm/test/CodeGen/LoongArch/frame.ll @@ -1,5 +1,6 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc --mtriple=loongarch64 -mattr=+d < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc --mtriple=loongarch64 -mattr=+d,-lsx < %s | FileCheck %s --check-prefixes=CHECK,NOLSX +; RUN: llc --mtriple=loongarch64 -mattr=+d,+lsx < %s | FileCheck %s --check-prefixes=CHECK,LSX %struct.key_t = type { i32, [16 x i8] } @@ -7,20 +8,35 @@ declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) declare void @test1(ptr) define i32 @test() nounwind { -; CHECK-LABEL: test: -; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -32 -; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -; CHECK-NEXT: st.w $zero, $sp, 16 -; CHECK-NEXT: vrepli.b $vr0, 0 -; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 4 -; CHECK-NEXT: pcaddu18i $ra, %call36(test1) -; CHECK-NEXT: jirl $ra, $ra, 0 -; CHECK-NEXT: move $a0, $zero -; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 32 -; CHECK-NEXT: ret +; NOLSX-LABEL: test: +; NOLSX: # %bb.0: +; NOLSX-NEXT: addi.d $sp, $sp, -32 +; NOLSX-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill +; NOLSX-NEXT: st.w $zero, $sp, 16 +; NOLSX-NEXT: st.d $zero, $sp, 8 +; NOLSX-NEXT: st.d $zero, $sp, 0 +; NOLSX-NEXT: addi.d $a0, $sp, 4 +; NOLSX-NEXT: pcaddu18i $ra, %call36(test1) +; NOLSX-NEXT: jirl $ra, $ra, 0 +; NOLSX-NEXT: move $a0, $zero +; NOLSX-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload +; NOLSX-NEXT: addi.d $sp, $sp, 32 +; NOLSX-NEXT: ret +; +; LSX-LABEL: test: +; LSX: # %bb.0: +; LSX-NEXT: addi.d $sp, $sp, -32 +; LSX-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill +; LSX-NEXT: st.w $zero, $sp, 16 +; LSX-NEXT: vrepli.b $vr0, 0 +; LSX-NEXT: vst $vr0, $sp, 0 +; LSX-NEXT: addi.d $a0, $sp, 4 +; LSX-NEXT: pcaddu18i $ra, %call36(test1) +; LSX-NEXT: jirl $ra, $ra, 0 +; LSX-NEXT: move $a0, $zero +; LSX-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload +; LSX-NEXT: addi.d $sp, $sp, 32 +; LSX-NEXT: ret %key = alloca %struct.key_t, align 4 call void @llvm.memset.p0.i64(ptr %key, i8 0, i64 20, i1 false) %1 = getelementptr inbounds %struct.key_t, ptr %key, i64 0, i32 1, i64 0 @@ -98,3 +114,62 @@ define void @test_large_frame_size_1234576() "frame-pointer"="all" { %1 = alloca i8, i32 1234567 ret void } + +;; Note: will create an emergency spill slot, if (!isInt<7>(StackSize)). +;; Should involve only one SP-adjusting addi per adjustment. +;; LSX 112 + 16(emergency solt) = 128 +define void @test_frame_size_112() { +; NOLSX-LABEL: test_frame_size_112: +; NOLSX: # %bb.0: +; NOLSX-NEXT: addi.d $sp, $sp, -112 +; NOLSX-NEXT: .cfi_def_cfa_offset 112 +; NOLSX-NEXT: addi.d $sp, $sp, 112 +; NOLSX-NEXT: ret +; +; LSX-LABEL: test_frame_size_112: +; LSX: # %bb.0: +; LSX-NEXT: addi.d $sp, $sp, -128 +; LSX-NEXT: .cfi_def_cfa_offset 128 +; LSX-NEXT: addi.d $sp, $sp, 128 +; LSX-NEXT: ret + %1 = alloca i8, i32 112 + ret void +} + +;; LSX 128 + 16(emergency solt) = 144 +define void @test_frame_size_128() { +; NOLSX-LABEL: test_frame_size_128: +; NOLSX: # %bb.0: +; NOLSX-NEXT: addi.d $sp, $sp, -128 +; NOLSX-NEXT: .cfi_def_cfa_offset 128 +; NOLSX-NEXT: addi.d $sp, $sp, 128 +; NOLSX-NEXT: ret +; +; LSX-LABEL: test_frame_size_128: +; LSX: # %bb.0: +; LSX-NEXT: addi.d $sp, $sp, -144 +; LSX-NEXT: .cfi_def_cfa_offset 144 +; LSX-NEXT: addi.d $sp, $sp, 144 +; LSX-NEXT: ret + %1 = alloca i8, i32 128 + ret void +} + +;; LSX 144 + 16(emergency solt) = 160 +define void @test_frame_size_144() { +; NOLSX-LABEL: test_frame_size_144: +; NOLSX: # %bb.0: +; NOLSX-NEXT: addi.d $sp, $sp, -144 +; NOLSX-NEXT: .cfi_def_cfa_offset 144 +; NOLSX-NEXT: addi.d $sp, $sp, 144 +; NOLSX-NEXT: ret +; +; LSX-LABEL: test_frame_size_144: +; LSX: # %bb.0: +; LSX-NEXT: addi.d $sp, $sp, -160 +; LSX-NEXT: .cfi_def_cfa_offset 160 +; LSX-NEXT: addi.d $sp, $sp, 160 +; LSX-NEXT: ret + %1 = alloca i8, i32 144 + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll index 565ccdbe6880f..38e06d15670a8 100644 --- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll +++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll @@ -142,6 +142,44 @@ define i32 @m_offset_2048(ptr %p) nounwind { ret i32 %2 } +define i32 @m_constant_0() nounwind { +; LA32-LABEL: m_constant_0: +; LA32: # %bb.0: +; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI7_0) +; LA32-NEXT: #APP +; LA32-NEXT: #NO_APP +; LA32-NEXT: ret +; +; LA64-LABEL: m_constant_0: +; LA64: # %bb.0: +; LA64-NEXT: pcalau12i $a0, %pc_hi20(.LCPI7_0) +; LA64-NEXT: #APP +; LA64-NEXT: #NO_APP +; LA64-NEXT: ret + %1 = call i32 asm sideeffect "", "=r,m"(i64 0) + ret i32 %1 +} + +define i32 @m_constant_1() nounwind { +; LA32-LABEL: m_constant_1: +; LA32: # %bb.0: +; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI8_0) +; LA32-NEXT: #APP +; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(.LCPI8_0) +; LA32-NEXT: #NO_APP +; LA32-NEXT: ret +; +; LA64-LABEL: m_constant_1: +; LA64: # %bb.0: +; LA64-NEXT: pcalau12i $a0, %pc_hi20(.LCPI8_0) +; LA64-NEXT: #APP +; LA64-NEXT: ld.w $a0, $a0, %pc_lo12(.LCPI8_0) +; LA64-NEXT: #NO_APP +; LA64-NEXT: ret + %1 = call i32 asm sideeffect "ld.w $0, $1", "=r,m"(i64 1) + ret i32 %1 +} + @g_i32 = dso_local global i32 0 define i32 @m_addr_pcrel() nounwind { diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll b/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll index 402ddb9ad941b..5a55b253c77bb 100644 --- a/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-memcpy.ll @@ -6,11 +6,11 @@ define void @box(ptr noalias nocapture noundef writeonly sret(%Box) align 16 dereferenceable(48) %b, i64 %i) { ; CHECK-LABEL: box: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -96 -; CHECK-NEXT: .cfi_def_cfa_offset 96 +; CHECK-NEXT: addi.d $sp, $sp, -112 +; CHECK-NEXT: .cfi_def_cfa_offset 112 ; CHECK-NEXT: slli.d $a2, $a1, 5 ; CHECK-NEXT: alsl.d $a1, $a1, $a2, 4 -; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: addi.d $a2, $sp, 16 ; CHECK-NEXT: add.d $a3, $a2, $a1 ; CHECK-NEXT: vldx $vr0, $a1, $a2 ; CHECK-NEXT: vld $vr1, $a3, 32 @@ -18,7 +18,7 @@ define void @box(ptr noalias nocapture noundef writeonly sret(%Box) align 16 der ; CHECK-NEXT: vst $vr0, $a0, 0 ; CHECK-NEXT: vst $vr1, $a0, 32 ; CHECK-NEXT: vst $vr2, $a0, 16 -; CHECK-NEXT: addi.d $sp, $sp, 96 +; CHECK-NEXT: addi.d $sp, $sp, 112 ; CHECK-NEXT: ret %1 = alloca [2 x %Box], align 16 %2 = getelementptr inbounds [2 x %Box], ptr %1, i64 0, i64 %i diff --git a/llvm/test/CodeGen/LoongArch/issue163681.ll b/llvm/test/CodeGen/LoongArch/issue163681.ll new file mode 100644 index 0000000000000..f6df349253045 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/issue163681.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc --mtriple=loongarch64 -code-model=large --verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +@.str = external constant [1 x i8] + +define void @caller(ptr %0) { +; CHECK-LABEL: caller: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: .cfi_offset 1, -8 +; CHECK-NEXT: ld.w $a2, $zero, 0 +; CHECK-NEXT: ld.d $a1, $a0, 0 +; CHECK-NEXT: beqz $a2, .LBB0_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: pcalau12i $a0, %got_pc_hi20(.str) +; CHECK-NEXT: addi.d $a2, $zero, %got_pc_lo12(.str) +; CHECK-NEXT: lu32i.d $a2, %got64_pc_lo20(.str) +; CHECK-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(.str) +; CHECK-NEXT: ldx.d $a2, $a2, $a0 +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: jirl $ra, $zero, 0 +; CHECK-NEXT: b .LBB0_3 +; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: pcalau12i $a0, %got_pc_hi20(.str) +; CHECK-NEXT: addi.d $a2, $zero, %got_pc_lo12(.str) +; CHECK-NEXT: lu32i.d $a2, %got64_pc_lo20(.str) +; CHECK-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(.str) +; CHECK-NEXT: ldx.d $a2, $a2, $a0 +; CHECK-NEXT: move $a0, $zero +; CHECK-NEXT: move $a3, $zero +; CHECK-NEXT: jirl $ra, $zero, 0 +; CHECK-NEXT: .LBB0_3: +; CHECK-NEXT: st.d $zero, $zero, 0 +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: ret + %2 = load i32, ptr null, align 4 + %3 = icmp eq i32 %2, 0 + %4 = load i64, ptr %0, align 8 + br i1 %3, label %6, label %5 + +5: ; preds = %1 + call void null(ptr null, i64 %4, ptr @.str) + br label %7 + +6: ; preds = %1 + tail call void null(ptr null, i64 %4, ptr @.str, i32 0) + br label %7 + +7: ; preds = %6, %5 + store ptr null, ptr null, align 8 + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/lasx/broadcast-load.ll b/llvm/test/CodeGen/LoongArch/lasx/broadcast-load.ll index 976924bdca686..6035b8822cef7 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/broadcast-load.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/broadcast-load.ll @@ -18,6 +18,32 @@ define <4 x i64> @should_not_be_optimized(ptr %ptr, ptr %dst) { ret <4 x i64> %tmp2 } +define <16 x i16> @should_not_be_optimized_sext_load(ptr %ptr) { +; CHECK-LABEL: should_not_be_optimized_sext_load: +; CHECK: # %bb.0: +; CHECK-NEXT: ld.b $a0, $a0, 0 +; CHECK-NEXT: xvreplgr2vr.h $xr0, $a0 +; CHECK-NEXT: ret + %tmp = load i8, ptr %ptr + %tmp1 = sext i8 %tmp to i16 + %tmp2 = insertelement <16 x i16> zeroinitializer, i16 %tmp1, i32 0 + %tmp3 = shufflevector <16 x i16> %tmp2, <16 x i16> poison, <16 x i32> zeroinitializer + ret <16 x i16> %tmp3 +} + +define <16 x i16> @should_not_be_optimized_zext_load(ptr %ptr) { +; CHECK-LABEL: should_not_be_optimized_zext_load: +; CHECK: # %bb.0: +; CHECK-NEXT: ld.bu $a0, $a0, 0 +; CHECK-NEXT: xvreplgr2vr.h $xr0, $a0 +; CHECK-NEXT: ret + %tmp = load i8, ptr %ptr + %tmp1 = zext i8 %tmp to i16 + %tmp2 = insertelement <16 x i16> zeroinitializer, i16 %tmp1, i32 0 + %tmp3 = shufflevector <16 x i16> %tmp2, <16 x i16> poison, <16 x i32> zeroinitializer + ret <16 x i16> %tmp3 +} + define <4 x i64> @xvldrepl_d_unaligned_offset(ptr %ptr) { ; CHECK-LABEL: xvldrepl_d_unaligned_offset: ; CHECK: # %bb.0: diff --git a/llvm/test/CodeGen/LoongArch/lasx/fpowi.ll b/llvm/test/CodeGen/LoongArch/lasx/fpowi.ll index 789b51d9b5e5b..9528280d181a3 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/fpowi.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/fpowi.ll @@ -6,10 +6,10 @@ declare <8 x float> @llvm.powi.v8f32.i32(<8 x float>, i32) define <8 x float> @powi_v8f32(<8 x float> %va, i32 %b) nounwind { ; CHECK-LABEL: powi_v8f32: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -80 -; CHECK-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 64 # 8-byte Folded Spill -; CHECK-NEXT: xvst $xr0, $sp, 0 # 32-byte Folded Spill +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: xvst $xr0, $sp, 16 # 32-byte Folded Spill ; CHECK-NEXT: addi.w $fp, $a0, 0 ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 0 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 @@ -18,79 +18,79 @@ define <8 x float> @powi_v8f32(<8 x float> %va, i32 %b) nounwind { ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 1 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 1 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 2 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 2 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 3 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 3 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 4 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 4 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 5 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 5 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 6 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 6 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.w $a0, $xr0, 7 ; CHECK-NEXT: movgr2fr.w $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powisf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.s $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.w $xr0, $a0, 7 -; CHECK-NEXT: ld.d $fp, $sp, 64 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 80 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %res = call <8 x float> @llvm.powi.v8f32.i32(<8 x float> %va, i32 %b) @@ -102,10 +102,10 @@ declare <4 x double> @llvm.powi.v4f64.i32(<4 x double>, i32) define <4 x double> @powi_v4f64(<4 x double> %va, i32 %b) nounwind { ; CHECK-LABEL: powi_v4f64: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -80 -; CHECK-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 64 # 8-byte Folded Spill -; CHECK-NEXT: xvst $xr0, $sp, 0 # 32-byte Folded Spill +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: xvst $xr0, $sp, 16 # 32-byte Folded Spill ; CHECK-NEXT: addi.w $fp, $a0, 0 ; CHECK-NEXT: xvpickve2gr.d $a0, $xr0, 0 ; CHECK-NEXT: movgr2fr.d $fa0, $a0 @@ -114,39 +114,39 @@ define <4 x double> @powi_v4f64(<4 x double> %va, i32 %b) nounwind { ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.d $a0, $fa0 ; CHECK-NEXT: xvinsgr2vr.d $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.d $a0, $xr0, 1 ; CHECK-NEXT: movgr2fr.d $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powidf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.d $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.d $xr0, $a0, 1 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.d $a0, $xr0, 2 ; CHECK-NEXT: movgr2fr.d $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powidf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.d $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.d $xr0, $a0, 2 -; CHECK-NEXT: xvst $xr0, $sp, 32 # 32-byte Folded Spill -; CHECK-NEXT: xvld $xr0, $sp, 0 # 32-byte Folded Reload +; CHECK-NEXT: xvst $xr0, $sp, 48 # 32-byte Folded Spill +; CHECK-NEXT: xvld $xr0, $sp, 16 # 32-byte Folded Reload ; CHECK-NEXT: xvpickve2gr.d $a0, $xr0, 3 ; CHECK-NEXT: movgr2fr.d $fa0, $a0 ; CHECK-NEXT: move $a0, $fp ; CHECK-NEXT: pcaddu18i $ra, %call36(__powidf2) ; CHECK-NEXT: jirl $ra, $ra, 0 ; CHECK-NEXT: movfr2gr.d $a0, $fa0 -; CHECK-NEXT: xvld $xr0, $sp, 32 # 32-byte Folded Reload +; CHECK-NEXT: xvld $xr0, $sp, 48 # 32-byte Folded Reload ; CHECK-NEXT: xvinsgr2vr.d $xr0, $a0, 3 -; CHECK-NEXT: ld.d $fp, $sp, 64 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 80 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %res = call <4 x double> @llvm.powi.v4f64.i32(<4 x double> %va, i32 %b) diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll index 04214f5dfa9d2..2e1618748688a 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/extractelement.ll @@ -76,21 +76,21 @@ define void @extract_4xdouble(ptr %src, ptr %dst) nounwind { define void @extract_32xi8_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_32xi8_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 0 ; CHECK-NEXT: ld.b $a0, $a0, 0 ; CHECK-NEXT: st.b $a0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <32 x i8>, ptr %src %e = extractelement <32 x i8> %v, i32 %idx @@ -101,21 +101,21 @@ define void @extract_32xi8_idx(ptr %src, ptr %dst, i32 %idx) nounwind { define void @extract_16xi16_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_16xi16_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 1 ; CHECK-NEXT: ld.h $a0, $a0, 0 ; CHECK-NEXT: st.h $a0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <16 x i16>, ptr %src %e = extractelement <16 x i16> %v, i32 %idx @@ -126,21 +126,21 @@ define void @extract_16xi16_idx(ptr %src, ptr %dst, i32 %idx) nounwind { define void @extract_8xi32_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_8xi32_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 2 ; CHECK-NEXT: ld.w $a0, $a0, 0 ; CHECK-NEXT: st.w $a0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <8 x i32>, ptr %src %e = extractelement <8 x i32> %v, i32 %idx @@ -151,21 +151,21 @@ define void @extract_8xi32_idx(ptr %src, ptr %dst, i32 %idx) nounwind { define void @extract_4xi64_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_4xi64_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 3 ; CHECK-NEXT: ld.d $a0, $a0, 0 ; CHECK-NEXT: st.d $a0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <4 x i64>, ptr %src %e = extractelement <4 x i64> %v, i32 %idx @@ -176,21 +176,21 @@ define void @extract_4xi64_idx(ptr %src, ptr %dst, i32 %idx) nounwind { define void @extract_8xfloat_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_8xfloat_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 2 ; CHECK-NEXT: fld.s $fa0, $a0, 0 ; CHECK-NEXT: fst.s $fa0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <8 x float>, ptr %src %e = extractelement <8 x float> %v, i32 %idx @@ -201,21 +201,21 @@ define void @extract_8xfloat_idx(ptr %src, ptr %dst, i32 %idx) nounwind { define void @extract_4xdouble_idx(ptr %src, ptr %dst, i32 %idx) nounwind { ; CHECK-LABEL: extract_4xdouble_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 3 ; CHECK-NEXT: fld.d $fa0, $a0, 0 ; CHECK-NEXT: fst.d $fa0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <4 x double>, ptr %src %e = extractelement <4 x double> %v, i32 %idx diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-element.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-element.ll index 3fdc439e68679..c3d09953fbc44 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-element.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-element.ll @@ -4,18 +4,18 @@ define <32 x i8> @insert_extract_v32i8(<32 x i8> %a) nounwind { ; CHECK-LABEL: insert_extract_v32i8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: ld.b $a0, $sp, 31 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: ld.b $a0, $sp, 63 ; CHECK-NEXT: vinsgr2vr.b $vr0, $a0, 1 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %b = extractelement <32 x i8> %a, i32 31 @@ -26,18 +26,18 @@ entry: define <16 x i16> @insert_extract_v16i16(<16 x i16> %a) nounwind { ; CHECK-LABEL: insert_extract_v16i16: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: ld.h $a0, $sp, 30 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: ld.h $a0, $sp, 62 ; CHECK-NEXT: vinsgr2vr.h $vr0, $a0, 1 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %b = extractelement <16 x i16> %a, i32 15 diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-pair-elements.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-pair-elements.ll index 88c3e4367ffa7..f2d8dda1850b1 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-pair-elements.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insert-extract-pair-elements.ll @@ -4,23 +4,23 @@ define <32 x i8> @insert_extract_v32i8(<32 x i8> %a) nounwind { ; CHECK-LABEL: insert_extract_v32i8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: vpickve2gr.b $a0, $vr0, 15 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: ld.b $a1, $sp, 31 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: ld.b $a1, $sp, 63 ; CHECK-NEXT: vinsgr2vr.b $vr0, $a0, 1 ; CHECK-NEXT: xvori.b $xr1, $xr0, 0 ; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1 ; CHECK-NEXT: vinsgr2vr.b $vr1, $a1, 1 ; CHECK-NEXT: xvpermi.q $xr0, $xr1, 2 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %b_lo = extractelement <32 x i8> %a, i32 15 @@ -33,23 +33,23 @@ entry: define <16 x i16> @insert_extract_v16i16(<16 x i16> %a) nounwind { ; CHECK-LABEL: insert_extract_v16i16: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: vpickve2gr.h $a0, $vr0, 7 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: ld.h $a1, $sp, 30 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: ld.h $a1, $sp, 62 ; CHECK-NEXT: vinsgr2vr.h $vr0, $a0, 1 ; CHECK-NEXT: xvori.b $xr1, $xr0, 0 ; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1 ; CHECK-NEXT: vinsgr2vr.h $vr1, $a1, 1 ; CHECK-NEXT: xvpermi.q $xr0, $xr1, 2 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret entry: %b_lo = extractelement <16 x i16> %a, i32 7 diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll index 25106b456d2f7..a6c0b332abcb9 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll @@ -116,22 +116,22 @@ define void @insert_4xdouble(ptr %src, ptr %dst, double %in) nounwind { define void @insert_32xi8_idx(ptr %src, ptr %dst, i8 %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_32xi8_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a3, 4, 0 ; CHECK-NEXT: st.b $a2, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <32 x i8>, ptr %src %v_new = insertelement <32 x i8> %v, i8 %in, i32 %idx @@ -142,22 +142,22 @@ define void @insert_32xi8_idx(ptr %src, ptr %dst, i8 %in, i32 %idx) nounwind { define void @insert_16xi16_idx(ptr %src, ptr %dst, i16 %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_16xi16_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a3, 4, 1 ; CHECK-NEXT: st.h $a2, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <16 x i16>, ptr %src %v_new = insertelement <16 x i16> %v, i16 %in, i32 %idx @@ -168,22 +168,22 @@ define void @insert_16xi16_idx(ptr %src, ptr %dst, i16 %in, i32 %idx) nounwind { define void @insert_8xi32_idx(ptr %src, ptr %dst, i32 %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_8xi32_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a3, 4, 2 ; CHECK-NEXT: st.w $a2, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <8 x i32>, ptr %src %v_new = insertelement <8 x i32> %v, i32 %in, i32 %idx @@ -194,22 +194,22 @@ define void @insert_8xi32_idx(ptr %src, ptr %dst, i32 %in, i32 %idx) nounwind { define void @insert_4xi64_idx(ptr %src, ptr %dst, i64 %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_4xi64_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 -; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr0, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a3, 4, 3 ; CHECK-NEXT: st.d $a2, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <4 x i64>, ptr %src %v_new = insertelement <4 x i64> %v, i64 %in, i32 %idx @@ -220,22 +220,22 @@ define void @insert_4xi64_idx(ptr %src, ptr %dst, i64 %in, i32 %idx) nounwind { define void @insert_8xfloat_idx(ptr %src, ptr %dst, float %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_8xfloat_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 -; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr1, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 2 ; CHECK-NEXT: fst.s $fa0, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <8 x float>, ptr %src %v_new = insertelement <8 x float> %v, float %in, i32 %idx @@ -246,22 +246,22 @@ define void @insert_8xfloat_idx(ptr %src, ptr %dst, float %in, i32 %idx) nounwin define void @insert_4xdouble_idx(ptr %src, ptr %dst, double %in, i32 %idx) nounwind { ; CHECK-LABEL: insert_4xdouble_idx: ; CHECK: # %bb.0: -; CHECK-NEXT: addi.d $sp, $sp, -64 -; CHECK-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; CHECK-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; CHECK-NEXT: addi.d $fp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $sp, -96 +; CHECK-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $fp, $sp, 96 ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 -; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 +; CHECK-NEXT: xvst $xr1, $sp, 32 +; CHECK-NEXT: addi.d $a0, $sp, 32 ; CHECK-NEXT: bstrins.d $a0, $a2, 4, 3 ; CHECK-NEXT: fst.d $fa0, $a0, 0 -; CHECK-NEXT: xvld $xr0, $sp, 0 +; CHECK-NEXT: xvld $xr0, $sp, 32 ; CHECK-NEXT: xvst $xr0, $a1, 0 -; CHECK-NEXT: addi.d $sp, $fp, -64 -; CHECK-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; CHECK-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; CHECK-NEXT: addi.d $sp, $sp, 64 +; CHECK-NEXT: addi.d $sp, $fp, -96 +; CHECK-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 96 ; CHECK-NEXT: ret %v = load volatile <4 x double>, ptr %src %v_new = insertelement <4 x double> %v, double %in, i32 %idx diff --git a/llvm/test/CodeGen/LoongArch/llvm.sincos.ll b/llvm/test/CodeGen/LoongArch/llvm.sincos.ll index ffedd7f9e9438..648c19d509715 100644 --- a/llvm/test/CodeGen/LoongArch/llvm.sincos.ll +++ b/llvm/test/CodeGen/LoongArch/llvm.sincos.ll @@ -347,42 +347,42 @@ define { <2 x float>, <2 x float> } @test_sincos_v2f32(<2 x float> %a) #0 { ; ; LA64-LABEL: test_sincos_v2f32: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -64 -; LA64-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; LA64-NEXT: vst $vr0, $sp, 0 # 16-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -80 +; LA64-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill ; LA64-NEXT: vreplvei.w $vr0, $vr0, 0 -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sinf) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: # kill: def $f0 killed $f0 def $vr0 -; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 0 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload ; LA64-NEXT: vreplvei.w $vr0, $vr0, 1 -; LA64-NEXT: vst $vr0, $sp, 0 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sinf) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: # kill: def $f0 killed $f0 def $vr0 -; LA64-NEXT: vld $vr1, $sp, 16 # 16-byte Folded Reload +; LA64-NEXT: vld $vr1, $sp, 32 # 16-byte Folded Reload ; LA64-NEXT: vpackev.w $vr0, $vr0, $vr1 -; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cosf) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: # kill: def $f0 killed $f0 def $vr0 -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 0 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cosf) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: # kill: def $f0 killed $f0 def $vr0 -; LA64-NEXT: vld $vr1, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: vld $vr1, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: vpackev.w $vr1, $vr0, $vr1 -; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 64 +; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 80 ; LA64-NEXT: ret %result = call { <2 x float>, <2 x float> } @llvm.sincos.v2f32(<2 x float> %a) ret { <2 x float>, <2 x float> } %result @@ -439,48 +439,48 @@ define { <3 x float>, <3 x float> } @test_sincos_v3f32(<3 x float> %a) #0 { ; ; LA64-LABEL: test_sincos_v3f32: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -96 -; LA64-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -112 +; LA64-NEXT: st.d $ra, $sp, 104 # 8-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill ; LA64-NEXT: vreplvei.w $vr0, $vr0, 2 -; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sinf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 72 -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: fst.s $fa0, $sp, 88 +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: vreplvei.w $vr0, $vr0, 1 -; LA64-NEXT: vst $vr0, $sp, 0 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sinf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 68 -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: fst.s $fa0, $sp, 84 +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: vreplvei.w $vr0, $vr0, 0 -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sinf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 64 -; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload +; LA64-NEXT: fst.s $fa0, $sp, 80 +; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cosf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 56 -; LA64-NEXT: vld $vr0, $sp, 0 # 16-byte Folded Reload +; LA64-NEXT: fst.s $fa0, $sp, 72 +; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cosf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 52 -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: fst.s $fa0, $sp, 68 +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0 killed $f0 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cosf) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: fst.s $fa0, $sp, 48 -; LA64-NEXT: vld $vr0, $sp, 64 -; LA64-NEXT: vld $vr1, $sp, 48 -; LA64-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 96 +; LA64-NEXT: fst.s $fa0, $sp, 64 +; LA64-NEXT: vld $vr0, $sp, 80 +; LA64-NEXT: vld $vr1, $sp, 64 +; LA64-NEXT: ld.d $ra, $sp, 104 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 112 ; LA64-NEXT: ret %result = call { <3 x float>, <3 x float> } @llvm.sincos.v3f32(<3 x float> %a) ret { <3 x float>, <3 x float> } %result @@ -568,44 +568,44 @@ define { <2 x double>, <2 x double> } @test_sincos_v2f64(<2 x double> %a) #0 { ; ; LA64-LABEL: test_sincos_v2f64: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -64 -; LA64-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; LA64-NEXT: vst $vr0, $sp, 0 # 16-byte Folded Spill -; LA64-NEXT: vreplvei.d $vr0, $vr0, 0 +; LA64-NEXT: addi.d $sp, $sp, -80 +; LA64-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill ; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill +; LA64-NEXT: vreplvei.d $vr0, $vr0, 0 +; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sin) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: movfr2gr.d $a0, $fa0 ; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0 -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 0 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload ; LA64-NEXT: vreplvei.d $vr0, $vr0, 1 -; LA64-NEXT: vst $vr0, $sp, 0 # 16-byte Folded Spill +; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill ; LA64-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(sin) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: movfr2gr.d $a0, $fa0 -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload ; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 1 -; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 48 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cos) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: movfr2gr.d $a0, $fa0 ; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0 -; LA64-NEXT: vst $vr0, $sp, 16 # 16-byte Folded Spill -; LA64-NEXT: vld $vr0, $sp, 0 # 16-byte Folded Reload +; LA64-NEXT: vst $vr0, $sp, 32 # 16-byte Folded Spill +; LA64-NEXT: vld $vr0, $sp, 16 # 16-byte Folded Reload ; LA64-NEXT: # kill: def $f0_64 killed $f0_64 killed $vr0 ; LA64-NEXT: pcaddu18i $ra, %call36(cos) ; LA64-NEXT: jirl $ra, $ra, 0 ; LA64-NEXT: movfr2gr.d $a0, $fa0 -; LA64-NEXT: vld $vr1, $sp, 16 # 16-byte Folded Reload +; LA64-NEXT: vld $vr1, $sp, 32 # 16-byte Folded Reload ; LA64-NEXT: vinsgr2vr.d $vr1, $a0, 1 -; LA64-NEXT: vld $vr0, $sp, 32 # 16-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 64 +; LA64-NEXT: vld $vr0, $sp, 48 # 16-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 80 ; LA64-NEXT: ret %result = call { <2 x double>, <2 x double> } @llvm.sincos.v2f64(<2 x double> %a) ret { <2 x double>, <2 x double> } %result @@ -801,17 +801,17 @@ define { <2 x fp128>, <2 x fp128> } @test_sincos_v2f128(<2 x fp128> %a) #0 { ; ; LA64-LABEL: test_sincos_v2f128: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -80 -; LA64-NEXT: st.d $ra, $sp, 72 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 64 # 8-byte Folded Spill -; LA64-NEXT: st.d $s0, $sp, 56 # 8-byte Folded Spill -; LA64-NEXT: st.d $s1, $sp, 48 # 8-byte Folded Spill -; LA64-NEXT: st.d $s2, $sp, 40 # 8-byte Folded Spill -; LA64-NEXT: st.d $s3, $sp, 32 # 8-byte Folded Spill -; LA64-NEXT: st.d $s4, $sp, 24 # 8-byte Folded Spill -; LA64-NEXT: st.d $s5, $sp, 16 # 8-byte Folded Spill -; LA64-NEXT: st.d $s6, $sp, 8 # 8-byte Folded Spill -; LA64-NEXT: st.d $s7, $sp, 0 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -96 +; LA64-NEXT: st.d $ra, $sp, 88 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 80 # 8-byte Folded Spill +; LA64-NEXT: st.d $s0, $sp, 72 # 8-byte Folded Spill +; LA64-NEXT: st.d $s1, $sp, 64 # 8-byte Folded Spill +; LA64-NEXT: st.d $s2, $sp, 56 # 8-byte Folded Spill +; LA64-NEXT: st.d $s3, $sp, 48 # 8-byte Folded Spill +; LA64-NEXT: st.d $s4, $sp, 40 # 8-byte Folded Spill +; LA64-NEXT: st.d $s5, $sp, 32 # 8-byte Folded Spill +; LA64-NEXT: st.d $s6, $sp, 24 # 8-byte Folded Spill +; LA64-NEXT: st.d $s7, $sp, 16 # 8-byte Folded Spill ; LA64-NEXT: ld.d $fp, $a1, 16 ; LA64-NEXT: ld.d $s0, $a1, 24 ; LA64-NEXT: ld.d $s1, $a1, 0 @@ -847,17 +847,17 @@ define { <2 x fp128>, <2 x fp128> } @test_sincos_v2f128(<2 x fp128> %a) #0 { ; LA64-NEXT: st.d $s6, $s3, 16 ; LA64-NEXT: st.d $s5, $s3, 8 ; LA64-NEXT: st.d $s4, $s3, 0 -; LA64-NEXT: ld.d $s7, $sp, 0 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s6, $sp, 8 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s5, $sp, 16 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s4, $sp, 24 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s3, $sp, 32 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s2, $sp, 40 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s1, $sp, 48 # 8-byte Folded Reload -; LA64-NEXT: ld.d $s0, $sp, 56 # 8-byte Folded Reload -; LA64-NEXT: ld.d $fp, $sp, 64 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 72 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 80 +; LA64-NEXT: ld.d $s7, $sp, 16 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s6, $sp, 24 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s5, $sp, 32 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s4, $sp, 40 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s3, $sp, 48 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s2, $sp, 56 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s1, $sp, 64 # 8-byte Folded Reload +; LA64-NEXT: ld.d $s0, $sp, 72 # 8-byte Folded Reload +; LA64-NEXT: ld.d $fp, $sp, 80 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 88 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 96 ; LA64-NEXT: ret %result = call { <2 x fp128>, <2 x fp128> } @llvm.sincos.v2f128(<2 x fp128> %a) ret { <2 x fp128>, <2 x fp128> } %result diff --git a/llvm/test/CodeGen/LoongArch/lsx/broadcast-load.ll b/llvm/test/CodeGen/LoongArch/lsx/broadcast-load.ll index c46747ef30509..f058acf5e45e5 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/broadcast-load.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/broadcast-load.ll @@ -1,8 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc --mtriple=loongarch64 -mattr=+lsx < %s | FileCheck %s -; TODO: Load a element and splat it to a vector could be lowerd to vldrepl - ; A load has more than one user shouldn't be lowered to vldrepl define <2 x i64> @should_not_be_optimized(ptr %ptr, ptr %dst){ ; CHECK-LABEL: should_not_be_optimized: @@ -18,6 +16,32 @@ define <2 x i64> @should_not_be_optimized(ptr %ptr, ptr %dst){ ret <2 x i64> %tmp2 } +define <8 x i16> @should_not_be_optimized_sext_load(ptr %ptr) { +; CHECK-LABEL: should_not_be_optimized_sext_load: +; CHECK: # %bb.0: +; CHECK-NEXT: ld.b $a0, $a0, 0 +; CHECK-NEXT: vreplgr2vr.h $vr0, $a0 +; CHECK-NEXT: ret + %tmp = load i8, ptr %ptr + %tmp1 = sext i8 %tmp to i16 + %tmp2 = insertelement <8 x i16> zeroinitializer, i16 %tmp1, i32 0 + %tmp3 = shufflevector <8 x i16> %tmp2, <8 x i16> poison, <8 x i32> zeroinitializer + ret <8 x i16> %tmp3 +} + +define <8 x i16> @should_not_be_optimized_zext_load(ptr %ptr) { +; CHECK-LABEL: should_not_be_optimized_zext_load: +; CHECK: # %bb.0: +; CHECK-NEXT: ld.bu $a0, $a0, 0 +; CHECK-NEXT: vreplgr2vr.h $vr0, $a0 +; CHECK-NEXT: ret + %tmp = load i8, ptr %ptr + %tmp1 = zext i8 %tmp to i16 + %tmp2 = insertelement <8 x i16> zeroinitializer, i16 %tmp1, i32 0 + %tmp3 = shufflevector <8 x i16> %tmp2, <8 x i16> poison, <8 x i32> zeroinitializer + ret <8 x i16> %tmp3 +} + define <2 x i64> @vldrepl_d_unaligned_offset(ptr %ptr) { ; CHECK-LABEL: vldrepl_d_unaligned_offset: ; CHECK: # %bb.0: diff --git a/llvm/test/CodeGen/LoongArch/lsx/pr146455.ll b/llvm/test/CodeGen/LoongArch/lsx/pr146455.ll new file mode 100644 index 0000000000000..96159e5884d3f --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/lsx/pr146455.ll @@ -0,0 +1,287 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc --mtriple=loongarch64 -mattr=+d,+lsx --verify-machineinstrs < %s | FileCheck %s +define void @eliminate_frame_index(<16 x i8> %a) nounwind { +; CHECK-LABEL: eliminate_frame_index: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -240 +; CHECK-NEXT: st.d $ra, $sp, 232 # 8-byte Folded Spill +; CHECK-NEXT: st.d $fp, $sp, 224 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s0, $sp, 216 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s1, $sp, 208 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s2, $sp, 200 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s3, $sp, 192 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s4, $sp, 184 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s5, $sp, 176 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s6, $sp, 168 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s7, $sp, 160 # 8-byte Folded Spill +; CHECK-NEXT: st.d $s8, $sp, 152 # 8-byte Folded Spill +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $zero, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $ra, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $tp, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a0, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a1, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a2, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a3, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a4, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a5, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a6, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $a7, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t0, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t1, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t2, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t3, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t4, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t5, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t6, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t7, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $t8, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $fp, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s0, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s1, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s2, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s3, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s4, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s5, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s6, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s7, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.d $s8, $zero, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: st.d $a0, $sp, 0 # 8-byte Folded Spill +; CHECK-NEXT: addi.d $a0, $sp, 136 +; CHECK-NEXT: vstelm.b $vr0, $a0, 0, 0 +; CHECK-NEXT: ld.d $a0, $sp, 0 # 8-byte Folded Reload +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $zero +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $ra +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $tp +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a3 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a4 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a5 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a6 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $a7 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t3 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t4 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t5 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t6 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t7 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $t8 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $fp +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s0 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s2 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s3 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s4 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s5 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s6 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s7 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: #APP +; CHECK-NEXT: # reg use $s8 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ld.d $s8, $sp, 152 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s7, $sp, 160 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s6, $sp, 168 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s5, $sp, 176 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s4, $sp, 184 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s3, $sp, 192 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s2, $sp, 200 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s1, $sp, 208 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $s0, $sp, 216 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $fp, $sp, 224 # 8-byte Folded Reload +; CHECK-NEXT: ld.d $ra, $sp, 232 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 240 +; CHECK-NEXT: ret + %s = alloca [16 x i8] + %ss = alloca [128 x i8] + + %zero = call i64 asm sideeffect "addi.d $$zero, $$zero, 1", "={r0}"() + %ra = call i64 asm sideeffect "addi.d $$ra, $$zero, 1", "={r1}"() + %tp = call i64 asm sideeffect "addi.d $$tp, $$zero, 1", "={r2}"() + %a0 = call i64 asm sideeffect "addi.d $$a0, $$zero, 1", "={r4}"() + %a1 = call i64 asm sideeffect "addi.d $$a1, $$zero, 1", "={r5}"() + %a2 = call i64 asm sideeffect "addi.d $$a2, $$zero, 1", "={r6}"() + %a3 = call i64 asm sideeffect "addi.d $$a3, $$zero, 1", "={r7}"() + %a4 = call i64 asm sideeffect "addi.d $$a4, $$zero, 1", "={r8}"() + %a5 = call i64 asm sideeffect "addi.d $$a5, $$zero, 1", "={r9}"() + %a6 = call i64 asm sideeffect "addi.d $$a6, $$zero, 1", "={r10}"() + %a7 = call i64 asm sideeffect "addi.d $$a7, $$zero, 1", "={r11}"() + %t0 = call i64 asm sideeffect "addi.d $$t0, $$zero, 1", "={r12}"() + %t1 = call i64 asm sideeffect "addi.d $$t1, $$zero, 1", "={r13}"() + %t2 = call i64 asm sideeffect "addi.d $$t2, $$zero, 1", "={r14}"() + %t3 = call i64 asm sideeffect "addi.d $$t3, $$zero, 1", "={r15}"() + %t4 = call i64 asm sideeffect "addi.d $$t4, $$zero, 1", "={r16}"() + %t5 = call i64 asm sideeffect "addi.d $$t5, $$zero, 1", "={r17}"() + %t6 = call i64 asm sideeffect "addi.d $$t6, $$zero, 1", "={r18}"() + %t7 = call i64 asm sideeffect "addi.d $$t7, $$zero, 1", "={r19}"() + %t8 = call i64 asm sideeffect "addi.d $$t8, $$zero, 1", "={r20}"() + ;; r21 Reserved (Non-allocatable) + %s9 = call i64 asm sideeffect "addi.d $$s9, $$zero, 1", "={r22}"() + %s0 = call i64 asm sideeffect "addi.d $$s0, $$zero, 1", "={r23}"() + %s1 = call i64 asm sideeffect "addi.d $$s1, $$zero, 1", "={r24}"() + %s2 = call i64 asm sideeffect "addi.d $$s2, $$zero, 1", "={r25}"() + %s3 = call i64 asm sideeffect "addi.d $$s3, $$zero, 1", "={r26}"() + %s4 = call i64 asm sideeffect "addi.d $$s4, $$zero, 1", "={r27}"() + %s5 = call i64 asm sideeffect "addi.d $$s5, $$zero, 1", "={r28}"() + %s6 = call i64 asm sideeffect "addi.d $$s6, $$zero, 1", "={r29}"() + %s7 = call i64 asm sideeffect "addi.d $$s7, $$zero, 1", "={r30}"() + %s8 = call i64 asm sideeffect "addi.d $$s8, $$zero, 1", "={r31}"() + + %e = extractelement <16 x i8> %a, i64 0 + + store volatile i8 %e, ptr %s + + call void asm sideeffect "# reg use $0", "{r0}"(i64 %zero) + call void asm sideeffect "# reg use $0", "{r1}"(i64 %ra) + call void asm sideeffect "# reg use $0", "{r2}"(i64 %tp) + call void asm sideeffect "# reg use $0", "{r4}"(i64 %a0) + call void asm sideeffect "# reg use $0", "{r5}"(i64 %a1) + call void asm sideeffect "# reg use $0", "{r6}"(i64 %a2) + call void asm sideeffect "# reg use $0", "{r7}"(i64 %a3) + call void asm sideeffect "# reg use $0", "{r8}"(i64 %a4) + call void asm sideeffect "# reg use $0", "{r9}"(i64 %a5) + call void asm sideeffect "# reg use $0", "{r10}"(i64 %a6) + call void asm sideeffect "# reg use $0", "{r11}"(i64 %a7) + call void asm sideeffect "# reg use $0", "{r12}"(i64 %t0) + call void asm sideeffect "# reg use $0", "{r13}"(i64 %t1) + call void asm sideeffect "# reg use $0", "{r14}"(i64 %t2) + call void asm sideeffect "# reg use $0", "{r15}"(i64 %t3) + call void asm sideeffect "# reg use $0", "{r16}"(i64 %t4) + call void asm sideeffect "# reg use $0", "{r17}"(i64 %t5) + call void asm sideeffect "# reg use $0", "{r18}"(i64 %t6) + call void asm sideeffect "# reg use $0", "{r19}"(i64 %t7) + call void asm sideeffect "# reg use $0", "{r20}"(i64 %t8) + ;; r21 Reserved (Non-allocatable) + call void asm sideeffect "# reg use $0", "{r22}"(i64 %s9) + call void asm sideeffect "# reg use $0", "{r23}"(i64 %s0) + call void asm sideeffect "# reg use $0", "{r24}"(i64 %s1) + call void asm sideeffect "# reg use $0", "{r25}"(i64 %s2) + call void asm sideeffect "# reg use $0", "{r26}"(i64 %s3) + call void asm sideeffect "# reg use $0", "{r27}"(i64 %s4) + call void asm sideeffect "# reg use $0", "{r28}"(i64 %s5) + call void asm sideeffect "# reg use $0", "{r29}"(i64 %s6) + call void asm sideeffect "# reg use $0", "{r30}"(i64 %s7) + call void asm sideeffect "# reg use $0", "{r31}"(i64 %s8) + + ret void +} diff --git a/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll b/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll index 0ee30120f77a6..ad57bbf9ee5c0 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll @@ -588,3 +588,18 @@ define i2 @vmsk_trunc_i64(<2 x i64> %a) { %res = bitcast <2 x i1> %y to i2 ret i2 %res } + +define i4 @vmsk_eq_allzeros_v4i8(<4 x i8> %a) { +; CHECK-LABEL: vmsk_eq_allzeros_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: vseqi.b $vr0, $vr0, 0 +; CHECK-NEXT: vilvl.b $vr0, $vr0, $vr0 +; CHECK-NEXT: vilvl.h $vr0, $vr0, $vr0 +; CHECK-NEXT: vslli.w $vr0, $vr0, 24 +; CHECK-NEXT: vmskltz.w $vr0, $vr0 +; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0 +; CHECK-NEXT: ret + %1 = icmp eq <4 x i8> %a, zeroinitializer + %2 = bitcast <4 x i1> %1 to i4 + ret i4 %2 +} diff --git a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll index 9f15604fcca6b..69995a0721f8a 100644 --- a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll +++ b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll @@ -36,15 +36,15 @@ define void @caller(i32 %n) { ; ; LA64-LABEL: caller: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -64 -; LA64-NEXT: .cfi_def_cfa_offset 64 -; LA64-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill -; LA64-NEXT: st.d $s8, $sp, 40 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -128 +; LA64-NEXT: .cfi_def_cfa_offset 128 +; LA64-NEXT: st.d $ra, $sp, 120 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 112 # 8-byte Folded Spill +; LA64-NEXT: st.d $s8, $sp, 104 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 ; LA64-NEXT: .cfi_offset 31, -24 -; LA64-NEXT: addi.d $fp, $sp, 64 +; LA64-NEXT: addi.d $fp, $sp, 128 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: bstrins.d $sp, $zero, 5, 0 ; LA64-NEXT: move $s8, $sp @@ -54,14 +54,14 @@ define void @caller(i32 %n) { ; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: move $sp, $a0 -; LA64-NEXT: addi.d $a1, $s8, 0 +; LA64-NEXT: addi.d $a1, $s8, 64 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: addi.d $sp, $fp, -64 -; LA64-NEXT: ld.d $s8, $sp, 40 # 8-byte Folded Reload -; LA64-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 64 +; LA64-NEXT: addi.d $sp, $fp, -128 +; LA64-NEXT: ld.d $s8, $sp, 104 # 8-byte Folded Reload +; LA64-NEXT: ld.d $fp, $sp, 112 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 120 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 128 ; LA64-NEXT: ret %1 = alloca i8, i32 %n %2 = alloca i32, align 64 diff --git a/llvm/test/CodeGen/LoongArch/stack-realignment.ll b/llvm/test/CodeGen/LoongArch/stack-realignment.ll index 0645339358b64..0188884543adb 100644 --- a/llvm/test/CodeGen/LoongArch/stack-realignment.ll +++ b/llvm/test/CodeGen/LoongArch/stack-realignment.ll @@ -28,22 +28,22 @@ define void @caller32() { ; ; LA64-LABEL: caller32: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -32 -; LA64-NEXT: .cfi_def_cfa_offset 32 -; LA64-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -64 +; LA64-NEXT: .cfi_def_cfa_offset 64 +; LA64-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 -; LA64-NEXT: addi.d $fp, $sp, 32 +; LA64-NEXT: addi.d $fp, $sp, 64 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: bstrins.d $sp, $zero, 4, 0 -; LA64-NEXT: addi.d $a0, $sp, 0 +; LA64-NEXT: addi.d $a0, $sp, 32 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: addi.d $sp, $fp, -32 -; LA64-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 32 +; LA64-NEXT: addi.d $sp, $fp, -64 +; LA64-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 64 ; LA64-NEXT: ret %1 = alloca i8, align 32 call void @callee(ptr %1) @@ -102,22 +102,22 @@ define void @caller64() { ; ; LA64-LABEL: caller64: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -64 -; LA64-NEXT: .cfi_def_cfa_offset 64 -; LA64-NEXT: st.d $ra, $sp, 56 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 48 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -128 +; LA64-NEXT: .cfi_def_cfa_offset 128 +; LA64-NEXT: st.d $ra, $sp, 120 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 112 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 -; LA64-NEXT: addi.d $fp, $sp, 64 +; LA64-NEXT: addi.d $fp, $sp, 128 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: bstrins.d $sp, $zero, 5, 0 -; LA64-NEXT: addi.d $a0, $sp, 0 +; LA64-NEXT: addi.d $a0, $sp, 64 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: addi.d $sp, $fp, -64 -; LA64-NEXT: ld.d $fp, $sp, 48 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 56 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 64 +; LA64-NEXT: addi.d $sp, $fp, -128 +; LA64-NEXT: ld.d $fp, $sp, 112 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 120 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 128 ; LA64-NEXT: ret %1 = alloca i8, align 64 call void @callee(ptr %1) @@ -176,22 +176,22 @@ define void @caller128() { ; ; LA64-LABEL: caller128: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -128 -; LA64-NEXT: .cfi_def_cfa_offset 128 -; LA64-NEXT: st.d $ra, $sp, 120 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 112 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -256 +; LA64-NEXT: .cfi_def_cfa_offset 256 +; LA64-NEXT: st.d $ra, $sp, 248 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 240 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 -; LA64-NEXT: addi.d $fp, $sp, 128 +; LA64-NEXT: addi.d $fp, $sp, 256 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: bstrins.d $sp, $zero, 6, 0 -; LA64-NEXT: addi.d $a0, $sp, 0 +; LA64-NEXT: addi.d $a0, $sp, 128 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: addi.d $sp, $fp, -128 -; LA64-NEXT: ld.d $fp, $sp, 112 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 120 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 128 +; LA64-NEXT: addi.d $sp, $fp, -256 +; LA64-NEXT: ld.d $fp, $sp, 240 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 248 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 256 ; LA64-NEXT: ret %1 = alloca i8, align 128 call void @callee(ptr %1) @@ -250,22 +250,22 @@ define void @caller256() { ; ; LA64-LABEL: caller256: ; LA64: # %bb.0: -; LA64-NEXT: addi.d $sp, $sp, -256 -; LA64-NEXT: .cfi_def_cfa_offset 256 -; LA64-NEXT: st.d $ra, $sp, 248 # 8-byte Folded Spill -; LA64-NEXT: st.d $fp, $sp, 240 # 8-byte Folded Spill +; LA64-NEXT: addi.d $sp, $sp, -512 +; LA64-NEXT: .cfi_def_cfa_offset 512 +; LA64-NEXT: st.d $ra, $sp, 504 # 8-byte Folded Spill +; LA64-NEXT: st.d $fp, $sp, 496 # 8-byte Folded Spill ; LA64-NEXT: .cfi_offset 1, -8 ; LA64-NEXT: .cfi_offset 22, -16 -; LA64-NEXT: addi.d $fp, $sp, 256 +; LA64-NEXT: addi.d $fp, $sp, 512 ; LA64-NEXT: .cfi_def_cfa 22, 0 ; LA64-NEXT: bstrins.d $sp, $zero, 7, 0 -; LA64-NEXT: addi.d $a0, $sp, 0 +; LA64-NEXT: addi.d $a0, $sp, 256 ; LA64-NEXT: pcaddu18i $ra, %call36(callee) ; LA64-NEXT: jirl $ra, $ra, 0 -; LA64-NEXT: addi.d $sp, $fp, -256 -; LA64-NEXT: ld.d $fp, $sp, 240 # 8-byte Folded Reload -; LA64-NEXT: ld.d $ra, $sp, 248 # 8-byte Folded Reload -; LA64-NEXT: addi.d $sp, $sp, 256 +; LA64-NEXT: addi.d $sp, $fp, -512 +; LA64-NEXT: ld.d $fp, $sp, 496 # 8-byte Folded Reload +; LA64-NEXT: ld.d $ra, $sp, 504 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 512 ; LA64-NEXT: ret %1 = alloca i8, align 256 call void @callee(ptr %1) diff --git a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll index eb656ad94e28b..6e9d26ab362d6 100644 --- a/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll +++ b/llvm/test/CodeGen/LoongArch/target-abi-from-triple-edge-cases.ll @@ -24,9 +24,9 @@ ; NO-WARNING-NOT: warning: triple-implied ABI conflicts with provided target-abi 'lp64d', using target-abi ;; Check that ILP32-on-LA64 and LP64-on-LA32 combinations are handled properly. -; RUN: llc --mtriple=loongarch64 --target-abi=ilp32d --mattr=+d < %s 2>&1 \ +; RUN: llc --mtriple=loongarch64-linux-gnu --target-abi=ilp32d --mattr=+d < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=LP64D,32ON64 -; RUN: llc --mtriple=loongarch32 --target-abi=lp64d --mattr=+d < %s 2>&1 \ +; RUN: llc --mtriple=loongarch32-linux-gnu --target-abi=lp64d --mattr=+d < %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=ILP32D,64ON32 ; 32ON64: warning: 32-bit ABIs are not supported for 64-bit targets, ignoring and using triple-implied ABI @@ -49,12 +49,6 @@ ; LP64D-LP64F-NOF: warning: both target-abi and the triple-implied ABI are invalid, ignoring and using feature-implied ABI -;; Check that triple-implied ABI are invalid, use feature-implied ABI -; RUN: llc --mtriple=loongarch64 --mattr=-f < %s 2>&1 \ -; RUN: | FileCheck %s --check-prefixes=LP64S,LP64D-NONE-NOF - -; LP64D-NONE-NOF: warning: the triple-implied ABI is invalid, ignoring and using feature-implied ABI - define float @f(float %a) { ; ILP32D-LABEL: f: ; ILP32D: # %bb.0: diff --git a/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll b/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll index 925fdf3d60646..0d441e66a0c84 100644 --- a/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll +++ b/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll @@ -121,19 +121,19 @@ define void @t3() { ; ; LA64-LABEL: t3: ; LA64: # %bb.0: # %entry -; LA64-NEXT: addi.d $sp, $sp, -64 -; LA64-NEXT: .cfi_def_cfa_offset 64 +; LA64-NEXT: addi.d $sp, $sp, -80 +; LA64-NEXT: .cfi_def_cfa_offset 80 ; LA64-NEXT: pcalau12i $a0, %pc_hi20(.L.str) ; LA64-NEXT: addi.d $a0, $a0, %pc_lo12(.L.str) ; LA64-NEXT: ld.h $a1, $a0, 20 ; LA64-NEXT: ld.w $a2, $a0, 16 ; LA64-NEXT: ld.d $a3, $a0, 8 ; LA64-NEXT: ld.d $a0, $a0, 0 -; LA64-NEXT: st.h $a1, $sp, 20 -; LA64-NEXT: st.w $a2, $sp, 16 -; LA64-NEXT: st.d $a3, $sp, 8 -; LA64-NEXT: st.d $a0, $sp, 0 -; LA64-NEXT: addi.d $sp, $sp, 64 +; LA64-NEXT: st.h $a1, $sp, 36 +; LA64-NEXT: st.w $a2, $sp, 32 +; LA64-NEXT: st.d $a3, $sp, 24 +; LA64-NEXT: st.d $a0, $sp, 16 +; LA64-NEXT: addi.d $sp, $sp, 80 ; LA64-NEXT: ret entry: %msgbuf = alloca [64 x i8], align 1 diff --git a/llvm/test/CodeGen/LoongArch/vararg.ll b/llvm/test/CodeGen/LoongArch/vararg.ll index 939cd2015c5b1..bc4b8a77c7e15 100644 --- a/llvm/test/CodeGen/LoongArch/vararg.ll +++ b/llvm/test/CodeGen/LoongArch/vararg.ll @@ -47,7 +47,7 @@ define i64 @va1(ptr %fmt, ...) { ; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 ; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 ; LA64-WITHFP-NEXT: addi.d $a1, $fp, 16 -; LA64-WITHFP-NEXT: st.d $a1, $fp, -24 +; LA64-WITHFP-NEXT: st.d $a1, $fp, -32 ; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload ; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload ; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 @@ -94,7 +94,7 @@ define i64 @va1_va_arg(ptr %fmt, ...) nounwind { ; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 ; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 ; LA64-WITHFP-NEXT: addi.d $a1, $fp, 16 -; LA64-WITHFP-NEXT: st.d $a1, $fp, -24 +; LA64-WITHFP-NEXT: st.d $a1, $fp, -32 ; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload ; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload ; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 @@ -112,11 +112,11 @@ define i64 @va1_va_arg(ptr %fmt, ...) nounwind { define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; LA64-FPELIM-LABEL: va1_va_arg_alloca: ; LA64-FPELIM: # %bb.0: -; LA64-FPELIM-NEXT: addi.d $sp, $sp, -96 -; LA64-FPELIM-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -; LA64-FPELIM-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill -; LA64-FPELIM-NEXT: st.d $s0, $sp, 8 # 8-byte Folded Spill -; LA64-FPELIM-NEXT: addi.d $fp, $sp, 32 +; LA64-FPELIM-NEXT: addi.d $sp, $sp, -112 +; LA64-FPELIM-NEXT: st.d $ra, $sp, 40 # 8-byte Folded Spill +; LA64-FPELIM-NEXT: st.d $fp, $sp, 32 # 8-byte Folded Spill +; LA64-FPELIM-NEXT: st.d $s0, $sp, 24 # 8-byte Folded Spill +; LA64-FPELIM-NEXT: addi.d $fp, $sp, 48 ; LA64-FPELIM-NEXT: move $s0, $a1 ; LA64-FPELIM-NEXT: st.d $a7, $fp, 56 ; LA64-FPELIM-NEXT: st.d $a6, $fp, 48 @@ -126,7 +126,7 @@ define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; LA64-FPELIM-NEXT: st.d $a2, $fp, 16 ; LA64-FPELIM-NEXT: st.d $a1, $fp, 8 ; LA64-FPELIM-NEXT: addi.d $a0, $fp, 16 -; LA64-FPELIM-NEXT: st.d $a0, $fp, -32 +; LA64-FPELIM-NEXT: st.d $a0, $fp, -40 ; LA64-FPELIM-NEXT: addi.d $a0, $a1, 15 ; LA64-FPELIM-NEXT: bstrins.d $a0, $zero, 3, 0 ; LA64-FPELIM-NEXT: sub.d $a0, $sp, $a0 @@ -134,20 +134,20 @@ define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; LA64-FPELIM-NEXT: pcaddu18i $ra, %call36(notdead) ; LA64-FPELIM-NEXT: jirl $ra, $ra, 0 ; LA64-FPELIM-NEXT: move $a0, $s0 -; LA64-FPELIM-NEXT: addi.d $sp, $fp, -32 -; LA64-FPELIM-NEXT: ld.d $s0, $sp, 8 # 8-byte Folded Reload -; LA64-FPELIM-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload -; LA64-FPELIM-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -; LA64-FPELIM-NEXT: addi.d $sp, $sp, 96 +; LA64-FPELIM-NEXT: addi.d $sp, $fp, -48 +; LA64-FPELIM-NEXT: ld.d $s0, $sp, 24 # 8-byte Folded Reload +; LA64-FPELIM-NEXT: ld.d $fp, $sp, 32 # 8-byte Folded Reload +; LA64-FPELIM-NEXT: ld.d $ra, $sp, 40 # 8-byte Folded Reload +; LA64-FPELIM-NEXT: addi.d $sp, $sp, 112 ; LA64-FPELIM-NEXT: ret ; ; LA64-WITHFP-LABEL: va1_va_arg_alloca: ; LA64-WITHFP: # %bb.0: -; LA64-WITHFP-NEXT: addi.d $sp, $sp, -96 -; LA64-WITHFP-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill -; LA64-WITHFP-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill -; LA64-WITHFP-NEXT: st.d $s0, $sp, 8 # 8-byte Folded Spill -; LA64-WITHFP-NEXT: addi.d $fp, $sp, 32 +; LA64-WITHFP-NEXT: addi.d $sp, $sp, -112 +; LA64-WITHFP-NEXT: st.d $ra, $sp, 40 # 8-byte Folded Spill +; LA64-WITHFP-NEXT: st.d $fp, $sp, 32 # 8-byte Folded Spill +; LA64-WITHFP-NEXT: st.d $s0, $sp, 24 # 8-byte Folded Spill +; LA64-WITHFP-NEXT: addi.d $fp, $sp, 48 ; LA64-WITHFP-NEXT: move $s0, $a1 ; LA64-WITHFP-NEXT: st.d $a7, $fp, 56 ; LA64-WITHFP-NEXT: st.d $a6, $fp, 48 @@ -157,7 +157,7 @@ define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; LA64-WITHFP-NEXT: st.d $a2, $fp, 16 ; LA64-WITHFP-NEXT: st.d $a1, $fp, 8 ; LA64-WITHFP-NEXT: addi.d $a0, $fp, 16 -; LA64-WITHFP-NEXT: st.d $a0, $fp, -32 +; LA64-WITHFP-NEXT: st.d $a0, $fp, -40 ; LA64-WITHFP-NEXT: addi.d $a0, $a1, 15 ; LA64-WITHFP-NEXT: bstrins.d $a0, $zero, 3, 0 ; LA64-WITHFP-NEXT: sub.d $a0, $sp, $a0 @@ -165,11 +165,11 @@ define i64 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; LA64-WITHFP-NEXT: pcaddu18i $ra, %call36(notdead) ; LA64-WITHFP-NEXT: jirl $ra, $ra, 0 ; LA64-WITHFP-NEXT: move $a0, $s0 -; LA64-WITHFP-NEXT: addi.d $sp, $fp, -32 -; LA64-WITHFP-NEXT: ld.d $s0, $sp, 8 # 8-byte Folded Reload -; LA64-WITHFP-NEXT: ld.d $fp, $sp, 16 # 8-byte Folded Reload -; LA64-WITHFP-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload -; LA64-WITHFP-NEXT: addi.d $sp, $sp, 96 +; LA64-WITHFP-NEXT: addi.d $sp, $fp, -48 +; LA64-WITHFP-NEXT: ld.d $s0, $sp, 24 # 8-byte Folded Reload +; LA64-WITHFP-NEXT: ld.d $fp, $sp, 32 # 8-byte Folded Reload +; LA64-WITHFP-NEXT: ld.d $ra, $sp, 40 # 8-byte Folded Reload +; LA64-WITHFP-NEXT: addi.d $sp, $sp, 112 ; LA64-WITHFP-NEXT: ret %va = alloca ptr, align 8 call void @llvm.va_start(ptr %va) @@ -314,10 +314,10 @@ define void @va_aligned_stack_caller() nounwind { ; ; LA64-WITHFP-LABEL: va_aligned_stack_caller: ; LA64-WITHFP: # %bb.0: -; LA64-WITHFP-NEXT: addi.d $sp, $sp, -112 -; LA64-WITHFP-NEXT: st.d $ra, $sp, 104 # 8-byte Folded Spill -; LA64-WITHFP-NEXT: st.d $fp, $sp, 96 # 8-byte Folded Spill -; LA64-WITHFP-NEXT: addi.d $fp, $sp, 112 +; LA64-WITHFP-NEXT: addi.d $sp, $sp, -128 +; LA64-WITHFP-NEXT: st.d $ra, $sp, 120 # 8-byte Folded Spill +; LA64-WITHFP-NEXT: st.d $fp, $sp, 112 # 8-byte Folded Spill +; LA64-WITHFP-NEXT: addi.d $fp, $sp, 128 ; LA64-WITHFP-NEXT: ori $a0, $zero, 17 ; LA64-WITHFP-NEXT: st.d $a0, $sp, 48 ; LA64-WITHFP-NEXT: ori $a0, $zero, 16 @@ -336,23 +336,23 @@ define void @va_aligned_stack_caller() nounwind { ; LA64-WITHFP-NEXT: lu32i.d $a0, 335544 ; LA64-WITHFP-NEXT: lu52i.d $a0, $a0, -328 ; LA64-WITHFP-NEXT: st.d $a0, $sp, 16 -; LA64-WITHFP-NEXT: st.d $zero, $fp, -24 +; LA64-WITHFP-NEXT: st.d $zero, $fp, -40 ; LA64-WITHFP-NEXT: vrepli.b $vr0, 0 -; LA64-WITHFP-NEXT: vst $vr0, $fp, -40 +; LA64-WITHFP-NEXT: vst $vr0, $fp, -56 ; LA64-WITHFP-NEXT: ori $a5, $zero, 1000 ; LA64-WITHFP-NEXT: ori $a0, $zero, 1 ; LA64-WITHFP-NEXT: ori $a1, $zero, 11 -; LA64-WITHFP-NEXT: addi.d $a2, $fp, -48 +; LA64-WITHFP-NEXT: addi.d $a2, $fp, -64 ; LA64-WITHFP-NEXT: ori $a3, $zero, 12 ; LA64-WITHFP-NEXT: ori $a4, $zero, 13 ; LA64-WITHFP-NEXT: ori $a7, $zero, 1 -; LA64-WITHFP-NEXT: st.d $a5, $fp, -48 +; LA64-WITHFP-NEXT: st.d $a5, $fp, -64 ; LA64-WITHFP-NEXT: move $a6, $zero ; LA64-WITHFP-NEXT: pcaddu18i $ra, %call36(va_aligned_stack_callee) ; LA64-WITHFP-NEXT: jirl $ra, $ra, 0 -; LA64-WITHFP-NEXT: ld.d $fp, $sp, 96 # 8-byte Folded Reload -; LA64-WITHFP-NEXT: ld.d $ra, $sp, 104 # 8-byte Folded Reload -; LA64-WITHFP-NEXT: addi.d $sp, $sp, 112 +; LA64-WITHFP-NEXT: ld.d $fp, $sp, 112 # 8-byte Folded Reload +; LA64-WITHFP-NEXT: ld.d $ra, $sp, 120 # 8-byte Folded Reload +; LA64-WITHFP-NEXT: addi.d $sp, $sp, 128 ; LA64-WITHFP-NEXT: ret %1 = call i32 (i32, ...) @va_aligned_stack_callee(i32 1, i32 11, i256 1000, i32 12, i32 13, i128 18446744073709551616, i32 14, diff --git a/llvm/test/CodeGen/Mips/abiflags-soft-float.ll b/llvm/test/CodeGen/Mips/abiflags-soft-float.ll new file mode 100644 index 0000000000000..01821f2d9b6c6 --- /dev/null +++ b/llvm/test/CodeGen/Mips/abiflags-soft-float.ll @@ -0,0 +1,12 @@ +; RUN: llc -filetype=obj -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o tmp.o +; RUN: llvm-readobj -A tmp.o | FileCheck %s -check-prefix=OBJ +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o - | \ +; RUN: FileCheck %s -check-prefix=ASM + +; OBJ: FP ABI: Soft float +; ASM: .module softfloat + +define dso_local void @asm_is_null() "use-soft-float"="true" { + call void asm sideeffect "", ""() + ret void +} diff --git a/llvm/test/CodeGen/Mips/atomic-min-max.ll b/llvm/test/CodeGen/Mips/atomic-min-max.ll index 85bf6d02c7d8f..02ae8d2b7480e 100644 --- a/llvm/test/CodeGen/Mips/atomic-min-max.ll +++ b/llvm/test/CodeGen/Mips/atomic-min-max.ll @@ -3,6 +3,7 @@ ; RUN: llc -mtriple=mips-elf -O0 -mcpu=mips32r6 -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MIPSR6 ; RUN: llc -mtriple=mips-elf -O0 -mcpu=mips32r2 -mattr=+micromips -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MM ; RUN: llc -mtriple=mips-elf -O0 -mcpu=mips32r6 -mattr=+micromips -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MMR6 +; RUN: llc -mtriple=mipsel-elf -O0 -mcpu=mips2 -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MIPS2 ; RUN: llc -mtriple=mipsel-elf -O0 -mcpu=mips32 -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MIPS32 ; RUN: llc -mtriple=mipsel-elf -O0 -mcpu=mips32r2 -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MIPSEL ; RUN: llc -mtriple=mipsel-elf -O0 -mcpu=mips32r6 -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=MIPSELR6 @@ -31,6 +32,33 @@ define i32 @test_max_32(ptr nocapture %ptr, i32 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_max_32: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: $BB0_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($4) +; MIPS2-NEXT: slt $3, $2, $5 +; MIPS2-NEXT: move $1, $5 +; MIPS2-NEXT: beqz $3, $BB0_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB0_1 Depth=1 +; MIPS2-NEXT: j $BB0_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB0_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB0_1 Depth=1 +; MIPS2-NEXT: move $1, $2 +; MIPS2-NEXT: $BB0_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB0_1 Depth=1 +; MIPS2-NEXT: sc $1, 0($4) +; MIPS2-NEXT: beqz $1, $BB0_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_max_32: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: sync @@ -251,6 +279,33 @@ define i32 @test_min_32(ptr nocapture %ptr, i32 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_min_32: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: $BB1_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($4) +; MIPS2-NEXT: slt $3, $2, $5 +; MIPS2-NEXT: move $1, $2 +; MIPS2-NEXT: beqz $3, $BB1_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB1_1 Depth=1 +; MIPS2-NEXT: j $BB1_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB1_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB1_1 Depth=1 +; MIPS2-NEXT: move $1, $5 +; MIPS2-NEXT: $BB1_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB1_1 Depth=1 +; MIPS2-NEXT: sc $1, 0($4) +; MIPS2-NEXT: beqz $1, $BB1_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_min_32: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: sync @@ -471,6 +526,33 @@ define i32 @test_umax_32(ptr nocapture %ptr, i32 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umax_32: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: $BB2_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($4) +; MIPS2-NEXT: sltu $3, $2, $5 +; MIPS2-NEXT: move $1, $5 +; MIPS2-NEXT: beqz $3, $BB2_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB2_1 Depth=1 +; MIPS2-NEXT: j $BB2_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB2_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB2_1 Depth=1 +; MIPS2-NEXT: move $1, $2 +; MIPS2-NEXT: $BB2_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB2_1 Depth=1 +; MIPS2-NEXT: sc $1, 0($4) +; MIPS2-NEXT: beqz $1, $BB2_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umax_32: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: sync @@ -691,6 +773,33 @@ define i32 @test_umin_32(ptr nocapture %ptr, i32 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umin_32: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: $BB3_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($4) +; MIPS2-NEXT: sltu $3, $2, $5 +; MIPS2-NEXT: move $1, $2 +; MIPS2-NEXT: beqz $3, $BB3_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB3_1 Depth=1 +; MIPS2-NEXT: j $BB3_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB3_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB3_1 Depth=1 +; MIPS2-NEXT: move $1, $5 +; MIPS2-NEXT: $BB3_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB3_1 Depth=1 +; MIPS2-NEXT: sc $1, 0($4) +; MIPS2-NEXT: beqz $1, $BB3_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: sync +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umin_32: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: sync @@ -936,6 +1045,58 @@ define i16 @test_max_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_max_16: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 65535 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB4_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: sll $4, $4, 16 +; MIPS2-NEXT: sra $4, $4, 16 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: slt $5, $4, $7 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: beqz $5, $BB4_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB4_1 Depth=1 +; MIPS2-NEXT: j $BB4_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB4_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB4_1 Depth=1 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: $BB4_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB4_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB4_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_max_16: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -1476,6 +1637,58 @@ define i16 @test_min_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_min_16: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 65535 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB5_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: sll $4, $4, 16 +; MIPS2-NEXT: sra $4, $4, 16 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: slt $5, $4, $7 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: beqz $5, $BB5_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB5_1 Depth=1 +; MIPS2-NEXT: j $BB5_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB5_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB5_1 Depth=1 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: $BB5_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB5_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB5_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_min_16: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -2015,6 +2228,57 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umax_16: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 65535 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB6_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: andi $4, $4, 65535 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: sltu $5, $4, $7 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: beqz $5, $BB6_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB6_1 Depth=1 +; MIPS2-NEXT: j $BB6_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB6_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB6_1 Depth=1 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: $BB6_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB6_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB6_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umax_16: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -2553,6 +2817,57 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umin_16: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 65535 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB7_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: andi $4, $4, 65535 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: sltu $5, $4, $7 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: beqz $5, $BB7_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB7_1 Depth=1 +; MIPS2-NEXT: j $BB7_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB7_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB7_1 Depth=1 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: $BB7_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB7_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB7_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umin_16: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -3092,6 +3407,58 @@ define i8 @test_max_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_max_8: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 255 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB8_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: sll $4, $4, 24 +; MIPS2-NEXT: sra $4, $4, 24 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: slt $5, $4, $7 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: beqz $5, $BB8_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB8_1 Depth=1 +; MIPS2-NEXT: j $BB8_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB8_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB8_1 Depth=1 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: $BB8_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB8_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB8_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_max_8: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -3631,6 +3998,58 @@ define i8 @test_min_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_min_8: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 255 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB9_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: sll $4, $4, 24 +; MIPS2-NEXT: sra $4, $4, 24 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: slt $5, $4, $7 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: beqz $5, $BB9_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB9_1 Depth=1 +; MIPS2-NEXT: j $BB9_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB9_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB9_1 Depth=1 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: $BB9_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB9_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB9_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_min_8: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -4170,6 +4589,57 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umax_8: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 255 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB10_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: andi $4, $4, 255 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: sltu $5, $4, $7 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: beqz $5, $BB10_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB10_1 Depth=1 +; MIPS2-NEXT: j $BB10_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB10_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB10_1 Depth=1 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: $BB10_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB10_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB10_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umax_8: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 @@ -4708,6 +5178,57 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS-NEXT: jr $ra ; MIPS-NEXT: nop ; +; MIPS2-LABEL: test_umin_8: +; MIPS2: # %bb.0: # %entry +; MIPS2-NEXT: addiu $sp, $sp, -8 +; MIPS2-NEXT: .cfi_def_cfa_offset 8 +; MIPS2-NEXT: # kill: def $at killed $a1 +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $1, $zero, -4 +; MIPS2-NEXT: and $6, $4, $1 +; MIPS2-NEXT: andi $1, $4, 3 +; MIPS2-NEXT: sll $10, $1, 3 +; MIPS2-NEXT: ori $1, $zero, 255 +; MIPS2-NEXT: sllv $8, $1, $10 +; MIPS2-NEXT: nor $9, $zero, $8 +; MIPS2-NEXT: sllv $7, $5, $10 +; MIPS2-NEXT: $BB11_1: # %entry +; MIPS2-NEXT: # =>This Inner Loop Header: Depth=1 +; MIPS2-NEXT: ll $2, 0($6) +; MIPS2-NEXT: srav $4, $2, $10 +; MIPS2-NEXT: andi $4, $4, 255 +; MIPS2-NEXT: or $1, $zero, $4 +; MIPS2-NEXT: sllv $4, $4, $10 +; MIPS2-NEXT: sltu $5, $4, $7 +; MIPS2-NEXT: move $3, $4 +; MIPS2-NEXT: beqz $5, $BB11_3 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.2: # %entry +; MIPS2-NEXT: # in Loop: Header=BB11_1 Depth=1 +; MIPS2-NEXT: j $BB11_4 +; MIPS2-NEXT: nop +; MIPS2-NEXT: $BB11_3: # %entry +; MIPS2-NEXT: # in Loop: Header=BB11_1 Depth=1 +; MIPS2-NEXT: move $3, $7 +; MIPS2-NEXT: $BB11_4: # %entry +; MIPS2-NEXT: # in Loop: Header=BB11_1 Depth=1 +; MIPS2-NEXT: and $3, $3, $8 +; MIPS2-NEXT: and $4, $2, $9 +; MIPS2-NEXT: or $4, $4, $3 +; MIPS2-NEXT: sc $4, 0($6) +; MIPS2-NEXT: beqz $4, $BB11_1 +; MIPS2-NEXT: nop +; MIPS2-NEXT: # %bb.5: # %entry +; MIPS2-NEXT: .insn +; MIPS2-NEXT: # %bb.6: # %entry +; MIPS2-NEXT: sw $1, 4($sp) # 4-byte Folded Spill +; MIPS2-NEXT: # %bb.7: # %entry +; MIPS2-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS2-NEXT: sync +; MIPS2-NEXT: addiu $sp, $sp, 8 +; MIPS2-NEXT: jr $ra +; MIPS2-NEXT: nop +; ; MIPSR6-LABEL: test_umin_8: ; MIPSR6: # %bb.0: # %entry ; MIPSR6-NEXT: addiu $sp, $sp, -8 diff --git a/llvm/test/CodeGen/Mips/nan_lowering.ll b/llvm/test/CodeGen/Mips/nan_lowering.ll new file mode 100644 index 0000000000000..2a11278e14b6c --- /dev/null +++ b/llvm/test/CodeGen/Mips/nan_lowering.ll @@ -0,0 +1,25 @@ +; RUN: llc -mtriple=mips-linux-gnu -mattr=-nan2008 < %s | FileCheck %s +; RUN: llc -mtriple=mips-linux-gnu -mattr=+nan2008 < %s | FileCheck %s + +; Make sure that lowering does not corrupt the value of NaN values, +; regardless of what the NaN mode is. + +define float @test1() { +; CHECK: .4byte 0x7fc00000 + ret float bitcast (i32 u0x7fc00000 to float) +} + +define float @test2() { +; CHECK: .4byte 0x7fc00001 + ret float bitcast (i32 u0x7fc00001 to float) +} + +define float @test3() { +; CHECK: .4byte 0x7f800000 + ret float bitcast (i32 u0x7f800000 to float) +} + +define float @test4() { +; CHECK: .4byte 0x7f800001 + ret float bitcast (i32 u0x7f800001 to float) +} diff --git a/llvm/test/CodeGen/Mips/qnan.ll b/llvm/test/CodeGen/Mips/qnan.ll deleted file mode 100644 index e5b4aa1b42ee7..0000000000000 --- a/llvm/test/CodeGen/Mips/qnan.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: llc -O3 -mcpu=mips32r2 -mtriple=mips-linux-gnu < %s -o - | FileCheck %s -check-prefixes=MIPS_Legacy -; RUN: llc -O3 -mcpu=mips32r2 -mtriple=mips-linux-gnu -mattr=+nan2008 < %s -o - | FileCheck %s -check-prefixes=MIPS_NaN2008 - -define dso_local float @nan(float noundef %a, float noundef %b) local_unnamed_addr #0 { -; MIPS_Legacy: $CPI0_0: -; MIPS_Legacy-NEXT: .4byte 0x7fa00000 # float NaN - -; MIPS_NaN2008: $CPI0_0: -; MIPS_NaN2008-NEXT: .4byte 0x7fc00000 # float NaN - -entry: - %0 = tail call float @llvm.minimum.f32(float %a, float %b) - ret float %0 -} diff --git a/llvm/test/CodeGen/NVPTX/f16x2-instructions.ll b/llvm/test/CodeGen/NVPTX/f16x2-instructions.ll index d0e2c1817f696..3baefde072be7 100644 --- a/llvm/test/CodeGen/NVPTX/f16x2-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/f16x2-instructions.ll @@ -45,11 +45,12 @@ define <2 x half> @test_ret_const() #0 { define half @test_extract_0(<2 x half> %a) #0 { ; CHECK-LABEL: test_extract_0( ; CHECK: { -; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-NEXT: .reg .b16 %rs<2>; ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_0_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_extract_0_param_0]; +; CHECK-NEXT: { .reg .b16 tmp; mov.b32 {%rs1, tmp}, %r1; } ; CHECK-NEXT: st.param.b16 [func_retval0], %rs1; ; CHECK-NEXT: ret; %e = extractelement <2 x half> %a, i32 0 @@ -59,12 +60,13 @@ define half @test_extract_0(<2 x half> %a) #0 { define half @test_extract_1(<2 x half> %a) #0 { ; CHECK-LABEL: test_extract_1( ; CHECK: { -; CHECK-NEXT: .reg .b16 %rs<3>; +; CHECK-NEXT: .reg .b16 %rs<2>; ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_1_param_0]; -; CHECK-NEXT: st.param.b16 [func_retval0], %rs2; +; CHECK-NEXT: ld.param.b32 %r1, [test_extract_1_param_0]; +; CHECK-NEXT: { .reg .b16 tmp; mov.b32 {tmp, %rs1}, %r1; } +; CHECK-NEXT: st.param.b16 [func_retval0], %rs1; ; CHECK-NEXT: ret; %e = extractelement <2 x half> %a, i32 1 ret half %e @@ -80,8 +82,9 @@ define half @test_extract_i(<2 x half> %a, i64 %idx) #0 { ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.b64 %rd1, [test_extract_i_param_1]; -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_i_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_extract_i_param_0]; ; CHECK-NEXT: setp.eq.b64 %p1, %rd1, 0; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: selp.b16 %rs3, %rs1, %rs2, %p1; ; CHECK-NEXT: st.param.b16 [func_retval0], %rs3; ; CHECK-NEXT: ret; @@ -107,14 +110,16 @@ define <2 x half> @test_fadd(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<10>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fadd_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fadd_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fadd_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fadd_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: add.rn.f32 %r5, %r4, %r3; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NOF16-NEXT: add.rn.f32 %r8, %r7, %r6; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NOF16-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -143,7 +148,8 @@ define <2 x half> @test_fadd_imm_0(<2 x half> %a) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fadd_imm_0_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fadd_imm_0_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NOF16-NEXT: add.rn.f32 %r3, %r2, 0f40000000; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -175,7 +181,8 @@ define <2 x half> @test_fadd_imm_1(<2 x half> %a) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fadd_imm_1_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fadd_imm_1_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NOF16-NEXT: add.rn.f32 %r3, %r2, 0f40000000; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -207,14 +214,16 @@ define <2 x half> @test_fsub(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<10>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fsub_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fsub_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fsub_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fsub_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: sub.rn.f32 %r5, %r4, %r3; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NOF16-NEXT: sub.rn.f32 %r8, %r7, %r6; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NOF16-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -242,7 +251,8 @@ define <2 x half> @test_fneg(<2 x half> %a) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<8>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fneg_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fneg_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NOF16-NEXT: mov.b32 %r3, 0f00000000; ; CHECK-NOF16-NEXT: sub.rn.f32 %r4, %r3, %r2; @@ -275,14 +285,16 @@ define <2 x half> @test_fmul(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<10>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fmul_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fmul_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fmul_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fmul_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: mul.rn.f32 %r5, %r4, %r3; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NOF16-NEXT: mul.rn.f32 %r8, %r7, %r6; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NOF16-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -299,14 +311,16 @@ define <2 x half> @test_fdiv(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NEXT: .reg .b32 %r<10>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fdiv_param_0]; -; CHECK-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fdiv_param_1]; -; CHECK-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NEXT: ld.param.b32 %r2, [test_fdiv_param_1]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fdiv_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NEXT: div.rn.f32 %r5, %r4, %r3; ; CHECK-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NEXT: div.rn.f32 %r8, %r7, %r6; ; CHECK-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -331,10 +345,12 @@ define <2 x half> @test_frem(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NEXT: .reg .b32 %r<18>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_frem_param_0]; -; CHECK-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_frem_param_1]; -; CHECK-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NEXT: ld.param.b32 %r2, [test_frem_param_1]; +; CHECK-NEXT: ld.param.b32 %r1, [test_frem_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NEXT: div.rn.f32 %r5, %r4, %r3; ; CHECK-NEXT: cvt.rzi.f32.f32 %r6, %r5; ; CHECK-NEXT: neg.f32 %r7, %r6; @@ -342,8 +358,8 @@ define <2 x half> @test_frem(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NEXT: testp.infinite.f32 %p1, %r3; ; CHECK-NEXT: selp.f32 %r9, %r4, %r8, %p1; ; CHECK-NEXT: cvt.rn.f16.f32 %rs5, %r9; -; CHECK-NEXT: cvt.f32.f16 %r10, %rs3; -; CHECK-NEXT: cvt.f32.f16 %r11, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r10, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r11, %rs3; ; CHECK-NEXT: div.rn.f32 %r12, %r11, %r10; ; CHECK-NEXT: cvt.rzi.f32.f32 %r13, %r12; ; CHECK-NEXT: neg.f32 %r14, %r13; @@ -535,11 +551,13 @@ define <2 x half> @test_select_cc(<2 x half> %a, <2 x half> %b, <2 x half> %c, < ; CHECK-F16-NEXT: // %bb.0: ; CHECK-F16-NEXT: ld.param.b32 %r4, [test_select_cc_param_3]; ; CHECK-F16-NEXT: ld.param.b32 %r3, [test_select_cc_param_2]; -; CHECK-F16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_param_0]; +; CHECK-F16-NEXT: ld.param.b32 %r2, [test_select_cc_param_1]; +; CHECK-F16-NEXT: ld.param.b32 %r1, [test_select_cc_param_0]; ; CHECK-F16-NEXT: setp.neu.f16x2 %p1|%p2, %r3, %r4; -; CHECK-F16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_param_1]; -; CHECK-F16-NEXT: selp.b16 %rs5, %rs2, %rs4, %p2; -; CHECK-F16-NEXT: selp.b16 %rs6, %rs1, %rs3, %p1; +; CHECK-F16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-F16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-F16-NEXT: selp.b16 %rs5, %rs4, %rs2, %p2; +; CHECK-F16-NEXT: selp.b16 %rs6, %rs3, %rs1, %p1; ; CHECK-F16-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; CHECK-F16-NEXT: ret; ; @@ -550,18 +568,22 @@ define <2 x half> @test_select_cc(<2 x half> %a, <2 x half> %b, <2 x half> %c, < ; CHECK-NOF16-NEXT: .reg .b32 %r<9>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_param_3]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs5, %rs6}, [test_select_cc_param_2]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs5; +; CHECK-NOF16-NEXT: ld.param.b32 %r4, [test_select_cc_param_3]; +; CHECK-NOF16-NEXT: ld.param.b32 %r3, [test_select_cc_param_2]; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_select_cc_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_select_cc_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r4; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.neu.f32 %p1, %r6, %r5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs6; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs4; ; CHECK-NOF16-NEXT: setp.neu.f32 %p2, %r8, %r7; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs7, %rs8}, [test_select_cc_param_1]; -; CHECK-NOF16-NEXT: selp.b16 %rs9, %rs2, %rs8, %p2; -; CHECK-NOF16-NEXT: selp.b16 %rs10, %rs1, %rs7, %p1; +; CHECK-NOF16-NEXT: mov.b32 {%rs5, %rs6}, %r2; +; CHECK-NOF16-NEXT: mov.b32 {%rs7, %rs8}, %r1; +; CHECK-NOF16-NEXT: selp.b16 %rs9, %rs8, %rs6, %p2; +; CHECK-NOF16-NEXT: selp.b16 %rs10, %rs7, %rs5, %p1; ; CHECK-NOF16-NEXT: st.param.v2.b16 [func_retval0], {%rs10, %rs9}; ; CHECK-NOF16-NEXT: ret; %cc = fcmp une <2 x half> %c, %d @@ -579,11 +601,13 @@ define <2 x float> @test_select_cc_f32_f16(<2 x float> %a, <2 x float> %b, ; CHECK-F16-NEXT: // %bb.0: ; CHECK-F16-NEXT: ld.param.b32 %r2, [test_select_cc_f32_f16_param_3]; ; CHECK-F16-NEXT: ld.param.b32 %r1, [test_select_cc_f32_f16_param_2]; -; CHECK-F16-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_f32_f16_param_0]; +; CHECK-F16-NEXT: ld.param.b64 %rd2, [test_select_cc_f32_f16_param_1]; +; CHECK-F16-NEXT: ld.param.b64 %rd1, [test_select_cc_f32_f16_param_0]; ; CHECK-F16-NEXT: setp.neu.f16x2 %p1|%p2, %r1, %r2; -; CHECK-F16-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_select_cc_f32_f16_param_1]; -; CHECK-F16-NEXT: selp.f32 %r7, %r4, %r6, %p2; -; CHECK-F16-NEXT: selp.f32 %r8, %r3, %r5, %p1; +; CHECK-F16-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-F16-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-F16-NEXT: selp.f32 %r7, %r6, %r4, %p2; +; CHECK-F16-NEXT: selp.f32 %r8, %r5, %r3, %p1; ; CHECK-F16-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; ; CHECK-F16-NEXT: ret; ; @@ -595,18 +619,22 @@ define <2 x float> @test_select_cc_f32_f16(<2 x float> %a, <2 x float> %b, ; CHECK-NOF16-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_f32_f16_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_f32_f16_param_3]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_f32_f16_param_2]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NOF16-NEXT: setp.neu.f32 %p1, %r6, %r5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs2; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs4; -; CHECK-NOF16-NEXT: setp.neu.f32 %p2, %r8, %r7; -; CHECK-NOF16-NEXT: ld.param.v2.b32 {%r9, %r10}, [test_select_cc_f32_f16_param_1]; -; CHECK-NOF16-NEXT: selp.f32 %r11, %r4, %r10, %p2; -; CHECK-NOF16-NEXT: selp.f32 %r12, %r3, %r9, %p1; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_select_cc_f32_f16_param_3]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_select_cc_f32_f16_param_2]; +; CHECK-NOF16-NEXT: ld.param.b64 %rd2, [test_select_cc_f32_f16_param_1]; +; CHECK-NOF16-NEXT: ld.param.b64 %rd1, [test_select_cc_f32_f16_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs1; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs3; +; CHECK-NOF16-NEXT: setp.neu.f32 %p1, %r4, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs4; +; CHECK-NOF16-NEXT: setp.neu.f32 %p2, %r6, %r5; +; CHECK-NOF16-NEXT: mov.b64 {%r7, %r8}, %rd2; +; CHECK-NOF16-NEXT: mov.b64 {%r9, %r10}, %rd1; +; CHECK-NOF16-NEXT: selp.f32 %r11, %r10, %r8, %p2; +; CHECK-NOF16-NEXT: selp.f32 %r12, %r9, %r7, %p1; ; CHECK-NOF16-NEXT: st.param.v2.b32 [func_retval0], {%r12, %r11}; ; CHECK-NOF16-NEXT: ret; <2 x half> %c, <2 x half> %d) #0 { @@ -624,14 +652,18 @@ define <2 x half> @test_select_cc_f16_f32(<2 x half> %a, <2 x half> %b, ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_f16_f32_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_f16_f32_param_2]; -; CHECK-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_select_cc_f16_f32_param_3]; -; CHECK-NEXT: setp.neu.f32 %p1, %r3, %r5; -; CHECK-NEXT: setp.neu.f32 %p2, %r4, %r6; -; CHECK-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_f16_f32_param_1]; -; CHECK-NEXT: selp.b16 %rs5, %rs2, %rs4, %p2; -; CHECK-NEXT: selp.b16 %rs6, %rs1, %rs3, %p1; +; CHECK-NEXT: ld.param.b64 %rd2, [test_select_cc_f16_f32_param_3]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_select_cc_f16_f32_param_2]; +; CHECK-NEXT: ld.param.b32 %r2, [test_select_cc_f16_f32_param_1]; +; CHECK-NEXT: ld.param.b32 %r1, [test_select_cc_f16_f32_param_0]; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NEXT: setp.neu.f32 %p1, %r5, %r3; +; CHECK-NEXT: setp.neu.f32 %p2, %r6, %r4; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NEXT: selp.b16 %rs5, %rs4, %rs2, %p2; +; CHECK-NEXT: selp.b16 %rs6, %rs3, %rs1, %p1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; CHECK-NEXT: ret; <2 x float> %c, <2 x float> %d) #0 { @@ -664,13 +696,15 @@ define <2 x i1> @test_fcmp_une(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_une_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_une_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_une_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_une_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.neu.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.neu.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -705,13 +739,15 @@ define <2 x i1> @test_fcmp_ueq(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ueq_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ueq_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ueq_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ueq_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.equ.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.equ.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -746,13 +782,15 @@ define <2 x i1> @test_fcmp_ugt(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ugt_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ugt_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ugt_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ugt_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.gtu.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.gtu.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -787,13 +825,15 @@ define <2 x i1> @test_fcmp_uge(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_uge_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_uge_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_uge_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_uge_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.geu.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.geu.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -828,13 +868,15 @@ define <2 x i1> @test_fcmp_ult(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ult_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ult_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ult_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ult_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.ltu.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.ltu.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -869,13 +911,15 @@ define <2 x i1> @test_fcmp_ule(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ule_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ule_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ule_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ule_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.leu.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.leu.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -911,13 +955,15 @@ define <2 x i1> @test_fcmp_uno(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_uno_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_uno_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_uno_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_uno_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.nan.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.nan.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -952,13 +998,15 @@ define <2 x i1> @test_fcmp_one(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_one_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_one_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_one_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_one_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.ne.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.ne.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -993,13 +1041,15 @@ define <2 x i1> @test_fcmp_oeq(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_oeq_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_oeq_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_oeq_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_oeq_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.eq.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.eq.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1034,13 +1084,15 @@ define <2 x i1> @test_fcmp_ogt(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ogt_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ogt_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ogt_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ogt_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.gt.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.gt.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1075,13 +1127,15 @@ define <2 x i1> @test_fcmp_oge(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_oge_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_oge_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_oge_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_oge_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.ge.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.ge.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1116,13 +1170,15 @@ define <2 x i1> @test_fcmp_olt(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_olt_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_olt_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_olt_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_olt_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.lt.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.lt.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1157,13 +1213,15 @@ define <2 x i1> @test_fcmp_ole(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ole_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ole_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ole_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ole_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.le.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.le.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1198,13 +1256,15 @@ define <2 x i1> @test_fcmp_ord(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fcmp_ord_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fcmp_ord_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fcmp_ord_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fcmp_ord_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NOF16-NEXT: setp.num.f32 %p1, %r4, %r3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs3; ; CHECK-NOF16-NEXT: setp.num.f32 %p2, %r6, %r5; ; CHECK-NOF16-NEXT: selp.b16 %rs5, -1, 0, %p2; ; CHECK-NOF16-NEXT: st.param.b8 [func_retval0], %rs5; @@ -1222,7 +1282,8 @@ define <2 x i32> @test_fptosi_i32(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptosi_i32_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fptosi_i32_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rzi.s32.f16 %r2, %rs2; ; CHECK-NEXT: cvt.rzi.s32.f16 %r3, %rs1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r3, %r2}; @@ -1239,7 +1300,8 @@ define <2 x i64> @test_fptosi_i64(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptosi_i64_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fptosi_i64_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rzi.s64.f16 %rd1, %rs2; ; CHECK-NEXT: cvt.rzi.s64.f16 %rd2, %rs1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd2, %rd1}; @@ -1255,7 +1317,8 @@ define <2 x i32> @test_fptoui_2xi32(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptoui_2xi32_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fptoui_2xi32_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rzi.u32.f16 %r2, %rs2; ; CHECK-NEXT: cvt.rzi.u32.f16 %r3, %rs1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r3, %r2}; @@ -1272,7 +1335,8 @@ define <2 x i64> @test_fptoui_2xi64(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptoui_2xi64_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fptoui_2xi64_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rzi.u64.f16 %rd1, %rs2; ; CHECK-NEXT: cvt.rzi.u64.f16 %rd2, %rs1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd2, %rd1}; @@ -1369,16 +1433,17 @@ define <2 x half> @test_uitofp_2xi32_fadd(<2 x i32> %a, <2 x half> %b) #0 { ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: ; CHECK-NOF16-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_uitofp_2xi32_fadd_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r3, [test_uitofp_2xi32_fadd_param_1]; ; CHECK-NOF16-NEXT: cvt.rn.f16.u32 %rs1, %r1; ; CHECK-NOF16-NEXT: cvt.rn.f16.u32 %rs2, %r2; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_uitofp_2xi32_fadd_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs2; -; CHECK-NOF16-NEXT: add.rn.f32 %r6, %r4, %r5; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs4; +; CHECK-NOF16-NEXT: add.rn.f32 %r6, %r5, %r4; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs5, %r6; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs1; -; CHECK-NOF16-NEXT: add.rn.f32 %r9, %r7, %r8; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs3; +; CHECK-NOF16-NEXT: add.rn.f32 %r9, %r8, %r7; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs6, %r9; ; CHECK-NOF16-NEXT: mov.b32 %r10, {%rs6, %rs5}; ; CHECK-NOF16-NEXT: st.param.b32 [func_retval0], %r10; @@ -1411,16 +1476,17 @@ define <2 x half> @test_sitofp_2xi32_fadd(<2 x i32> %a, <2 x half> %b) #0 { ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: ; CHECK-NOF16-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_sitofp_2xi32_fadd_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r3, [test_sitofp_2xi32_fadd_param_1]; ; CHECK-NOF16-NEXT: cvt.rn.f16.s32 %rs1, %r1; ; CHECK-NOF16-NEXT: cvt.rn.f16.s32 %rs2, %r2; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_sitofp_2xi32_fadd_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs2; -; CHECK-NOF16-NEXT: add.rn.f32 %r6, %r4, %r5; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs4; +; CHECK-NOF16-NEXT: add.rn.f32 %r6, %r5, %r4; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs5, %r6; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs1; -; CHECK-NOF16-NEXT: add.rn.f32 %r9, %r7, %r8; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs3; +; CHECK-NOF16-NEXT: add.rn.f32 %r9, %r8, %r7; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs6, %r9; ; CHECK-NOF16-NEXT: mov.b32 %r10, {%rs6, %rs5}; ; CHECK-NOF16-NEXT: st.param.b32 [func_retval0], %r10; @@ -1468,7 +1534,8 @@ define <2 x float> @test_fpext_2xfloat(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fpext_2xfloat_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fpext_2xfloat_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NEXT: cvt.f32.f16 %r3, %rs1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r3, %r2}; @@ -1485,7 +1552,8 @@ define <2 x double> @test_fpext_2xdouble(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fpext_2xdouble_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_fpext_2xdouble_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f64.f16 %rd1, %rs2; ; CHECK-NEXT: cvt.f64.f16 %rd2, %rs1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd2, %rd1}; @@ -1578,7 +1646,8 @@ define <2 x half> @test_sqrt(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<7>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_sqrt_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_sqrt_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NEXT: sqrt.rn.f32 %r3, %r2; ; CHECK-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -1606,7 +1675,8 @@ define <2 x half> @test_sin(<2 x half> %a) #0 #1 { ; CHECK-NEXT: .reg .b32 %r<7>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_sin_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_sin_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NEXT: sin.approx.f32 %r3, %r2; ; CHECK-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -1627,7 +1697,8 @@ define <2 x half> @test_cos(<2 x half> %a) #0 #1 { ; CHECK-NEXT: .reg .b32 %r<7>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_cos_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_cos_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NEXT: cos.approx.f32 %r3, %r2; ; CHECK-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -1703,17 +1774,20 @@ define <2 x half> @test_fma(<2 x half> %a, <2 x half> %b, <2 x half> %c) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<13>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fma_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fma_param_2]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs5, %rs6}, [test_fma_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs6; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r3, [test_fma_param_2]; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fma_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fma_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs4; +; CHECK-NOF16-NEXT: mov.b32 {%rs5, %rs6}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs6; ; CHECK-NOF16-NEXT: fma.rn.f32 %r7, %r6, %r5, %r4; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs7, %r7; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r9, %rs5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r10, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r9, %rs3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r10, %rs5; ; CHECK-NOF16-NEXT: fma.rn.f32 %r11, %r10, %r9, %r8; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs8, %r11; ; CHECK-NOF16-NEXT: mov.b32 %r12, {%rs8, %rs7}; @@ -1740,7 +1814,8 @@ define <2 x half> @test_fabs(<2 x half> %a) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<7>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fabs_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fabs_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NOF16-NEXT: abs.f32 %r3, %r2; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs3, %r3; @@ -1761,14 +1836,16 @@ define <2 x half> @test_minnum(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NEXT: .reg .b32 %r<10>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_minnum_param_0]; -; CHECK-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_minnum_param_1]; -; CHECK-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NEXT: ld.param.b32 %r2, [test_minnum_param_1]; +; CHECK-NEXT: ld.param.b32 %r1, [test_minnum_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NEXT: min.f32 %r5, %r4, %r3; ; CHECK-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NEXT: min.f32 %r8, %r7, %r6; ; CHECK-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -1785,14 +1862,16 @@ define <2 x half> @test_maxnum(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NEXT: .reg .b32 %r<10>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_maxnum_param_0]; -; CHECK-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_maxnum_param_1]; -; CHECK-NEXT: cvt.f32.f16 %r3, %rs4; -; CHECK-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NEXT: ld.param.b32 %r2, [test_maxnum_param_1]; +; CHECK-NEXT: ld.param.b32 %r1, [test_maxnum_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.f32.f16 %r3, %rs2; +; CHECK-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; CHECK-NEXT: cvt.f32.f16 %r4, %rs4; ; CHECK-NEXT: max.f32 %r5, %r4, %r3; ; CHECK-NEXT: cvt.rn.f16.f32 %rs5, %r5; -; CHECK-NEXT: cvt.f32.f16 %r6, %rs3; -; CHECK-NEXT: cvt.f32.f16 %r7, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r6, %rs1; +; CHECK-NEXT: cvt.f32.f16 %r7, %rs3; ; CHECK-NEXT: max.f32 %r8, %r7, %r6; ; CHECK-NEXT: cvt.rn.f16.f32 %rs6, %r8; ; CHECK-NEXT: mov.b32 %r9, {%rs6, %rs5}; @@ -1822,13 +1901,15 @@ define <2 x half> @test_copysign(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<3>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_copysign_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_copysign_param_1]; -; CHECK-NOF16-NEXT: and.b16 %rs5, %rs4, -32768; -; CHECK-NOF16-NEXT: and.b16 %rs6, %rs2, 32767; -; CHECK-NOF16-NEXT: or.b16 %rs7, %rs6, %rs5; -; CHECK-NOF16-NEXT: and.b16 %rs8, %rs3, -32768; -; CHECK-NOF16-NEXT: and.b16 %rs9, %rs1, 32767; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_copysign_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_copysign_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: and.b16 %rs3, %rs2, -32768; +; CHECK-NOF16-NEXT: mov.b32 {%rs4, %rs5}, %r1; +; CHECK-NOF16-NEXT: and.b16 %rs6, %rs5, 32767; +; CHECK-NOF16-NEXT: or.b16 %rs7, %rs6, %rs3; +; CHECK-NOF16-NEXT: and.b16 %rs8, %rs1, -32768; +; CHECK-NOF16-NEXT: and.b16 %rs9, %rs4, 32767; ; CHECK-NOF16-NEXT: or.b16 %rs10, %rs9, %rs8; ; CHECK-NOF16-NEXT: st.param.v2.b16 [func_retval0], {%rs10, %rs7}; ; CHECK-NOF16-NEXT: ret; @@ -1844,8 +1925,9 @@ define <2 x half> @test_copysign_f32(<2 x half> %a, <2 x float> %b) #0 { ; CHECK-F16-NEXT: .reg .b64 %rd<2>; ; CHECK-F16-EMPTY: ; CHECK-F16-NEXT: // %bb.0: +; CHECK-F16-NEXT: ld.param.b64 %rd1, [test_copysign_f32_param_1]; ; CHECK-F16-NEXT: ld.param.b32 %r1, [test_copysign_f32_param_0]; -; CHECK-F16-NEXT: ld.param.v2.b32 {%r2, %r3}, [test_copysign_f32_param_1]; +; CHECK-F16-NEXT: mov.b64 {%r2, %r3}, %rd1; ; CHECK-F16-NEXT: cvt.rn.f16.f32 %rs1, %r3; ; CHECK-F16-NEXT: cvt.rn.f16.f32 %rs2, %r2; ; CHECK-F16-NEXT: mov.b32 %r4, {%rs2, %rs1}; @@ -1862,8 +1944,10 @@ define <2 x half> @test_copysign_f32(<2 x half> %a, <2 x float> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b64 %rd<2>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_copysign_f32_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b32 {%r2, %r3}, [test_copysign_f32_param_1]; +; CHECK-NOF16-NEXT: ld.param.b64 %rd1, [test_copysign_f32_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_copysign_f32_param_0]; +; CHECK-NOF16-NEXT: mov.b64 {%r2, %r3}, %rd1; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: and.b16 %rs3, %rs2, 32767; ; CHECK-NOF16-NEXT: and.b32 %r4, %r3, -2147483648; ; CHECK-NOF16-NEXT: { .reg .b16 tmp; mov.b32 {tmp, %rs4}, %r4; } @@ -1906,7 +1990,8 @@ define <2 x half> @test_copysign_f64(<2 x half> %a, <2 x double> %b) #0 { ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: ; CHECK-NOF16-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_copysign_f64_param_1]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_copysign_f64_param_0]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_copysign_f64_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NOF16-NEXT: and.b16 %rs3, %rs2, 32767; ; CHECK-NOF16-NEXT: and.b64 %rd3, %rd2, -9223372036854775808; ; CHECK-NOF16-NEXT: shr.u64 %rd4, %rd3, 48; @@ -1948,13 +2033,15 @@ define <2 x float> @test_copysign_extended(<2 x half> %a, <2 x half> %b) #0 { ; CHECK-NOF16-NEXT: .reg .b32 %r<5>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_copysign_extended_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_copysign_extended_param_1]; -; CHECK-NOF16-NEXT: and.b16 %rs5, %rs3, -32768; -; CHECK-NOF16-NEXT: and.b16 %rs6, %rs1, 32767; -; CHECK-NOF16-NEXT: or.b16 %rs7, %rs6, %rs5; -; CHECK-NOF16-NEXT: and.b16 %rs8, %rs4, -32768; -; CHECK-NOF16-NEXT: and.b16 %rs9, %rs2, 32767; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_copysign_extended_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_copysign_extended_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NOF16-NEXT: and.b16 %rs3, %rs1, -32768; +; CHECK-NOF16-NEXT: mov.b32 {%rs4, %rs5}, %r1; +; CHECK-NOF16-NEXT: and.b16 %rs6, %rs4, 32767; +; CHECK-NOF16-NEXT: or.b16 %rs7, %rs6, %rs3; +; CHECK-NOF16-NEXT: and.b16 %rs8, %rs2, -32768; +; CHECK-NOF16-NEXT: and.b16 %rs9, %rs5, 32767; ; CHECK-NOF16-NEXT: or.b16 %rs10, %rs9, %rs8; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r3, %rs10; ; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs7; @@ -1972,7 +2059,8 @@ define <2 x half> @test_floor(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_floor_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_floor_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rmi.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rmi.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -1988,7 +2076,8 @@ define <2 x half> @test_ceil(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_ceil_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_ceil_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rpi.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rpi.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2004,7 +2093,8 @@ define <2 x half> @test_trunc(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_trunc_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_trunc_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rzi.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rzi.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2020,7 +2110,8 @@ define <2 x half> @test_rint(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_rint_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_rint_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rni.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rni.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2036,7 +2127,8 @@ define <2 x half> @test_nearbyint(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_nearbyint_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_nearbyint_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rni.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rni.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2052,7 +2144,8 @@ define <2 x half> @test_roundeven(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_roundeven_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_roundeven_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rni.f16.f16 %rs3, %rs2; ; CHECK-NEXT: cvt.rni.f16.f16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2070,7 +2163,8 @@ define <2 x half> @test_round(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<21>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_round_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_round_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.f32.f16 %r2, %rs2; ; CHECK-NEXT: and.b32 %r3, %r2, -2147483648; ; CHECK-NEXT: or.b32 %r4, %r3, 1056964608; @@ -2121,17 +2215,20 @@ define <2 x half> @test_fmuladd(<2 x half> %a, <2 x half> %b, <2 x half> %c) #0 ; CHECK-NOF16-NEXT: .reg .b32 %r<13>; ; CHECK-NOF16-EMPTY: ; CHECK-NOF16-NEXT: // %bb.0: -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fmuladd_param_0]; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_fmuladd_param_2]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs4; -; CHECK-NOF16-NEXT: ld.param.v2.b16 {%rs5, %rs6}, [test_fmuladd_param_1]; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs6; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs2; +; CHECK-NOF16-NEXT: ld.param.b32 %r3, [test_fmuladd_param_2]; +; CHECK-NOF16-NEXT: ld.param.b32 %r2, [test_fmuladd_param_1]; +; CHECK-NOF16-NEXT: ld.param.b32 %r1, [test_fmuladd_param_0]; +; CHECK-NOF16-NEXT: mov.b32 {%rs1, %rs2}, %r3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r4, %rs2; +; CHECK-NOF16-NEXT: mov.b32 {%rs3, %rs4}, %r2; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r5, %rs4; +; CHECK-NOF16-NEXT: mov.b32 {%rs5, %rs6}, %r1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r6, %rs6; ; CHECK-NOF16-NEXT: fma.rn.f32 %r7, %r6, %r5, %r4; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs7, %r7; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs3; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r9, %rs5; -; CHECK-NOF16-NEXT: cvt.f32.f16 %r10, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r8, %rs1; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r9, %rs3; +; CHECK-NOF16-NEXT: cvt.f32.f16 %r10, %rs5; ; CHECK-NOF16-NEXT: fma.rn.f32 %r11, %r10, %r9, %r8; ; CHECK-NOF16-NEXT: cvt.rn.f16.f32 %rs8, %r11; ; CHECK-NOF16-NEXT: mov.b32 %r12, {%rs8, %rs7}; @@ -2148,7 +2245,8 @@ define <2 x half> @test_shufflevector(<2 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_shufflevector_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_shufflevector_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; ; CHECK-NEXT: ret; %s = shufflevector <2 x half> %a, <2 x half> undef, <2 x i32> @@ -2158,12 +2256,13 @@ define <2 x half> @test_shufflevector(<2 x half> %a) #0 { define <2 x half> @test_insertelement(<2 x half> %a, half %x) #0 { ; CHECK-LABEL: test_insertelement( ; CHECK: { -; CHECK-NEXT: .reg .b16 %rs<4>; +; CHECK-NEXT: .reg .b16 %rs<3>; ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.b16 %rs1, [test_insertelement_param_1]; -; CHECK-NEXT: ld.param.v2.b16 {%rs2, %rs3}, [test_insertelement_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_insertelement_param_0]; +; CHECK-NEXT: { .reg .b16 tmp; mov.b32 {%rs2, tmp}, %r1; } ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; ; CHECK-NEXT: ret; %i = insertelement <2 x half> %a, half %x, i64 1 @@ -2177,7 +2276,8 @@ define <2 x half> @test_sitofp_2xi16_to_2xhalf(<2 x i16> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_sitofp_2xi16_to_2xhalf_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_sitofp_2xi16_to_2xhalf_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rn.f16.s16 %rs3, %rs2; ; CHECK-NEXT: cvt.rn.f16.s16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -2193,7 +2293,8 @@ define <2 x half> @test_uitofp_2xi16_to_2xhalf(<2 x i16> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_uitofp_2xi16_to_2xhalf_param_0]; +; CHECK-NEXT: ld.param.b32 %r1, [test_uitofp_2xi16_to_2xhalf_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; CHECK-NEXT: cvt.rn.f16.u16 %rs3, %rs2; ; CHECK-NEXT: cvt.rn.f16.u16 %rs4, %rs1; ; CHECK-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; diff --git a/llvm/test/CodeGen/NVPTX/f32x2-instructions.ll b/llvm/test/CodeGen/NVPTX/f32x2-instructions.ll index af3cb63082e78..da9e2d8cba139 100644 --- a/llvm/test/CodeGen/NVPTX/f32x2-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/f32x2-instructions.ll @@ -28,29 +28,53 @@ define <2 x float> @test_ret_const() #0 { } define float @test_extract_0(<2 x float> %a) #0 { -; CHECK-LABEL: test_extract_0( -; CHECK: { -; CHECK-NEXT: .reg .b32 %r<3>; -; CHECK-NEXT: .reg .b64 %rd<2>; -; CHECK-EMPTY: -; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_extract_0_param_0]; -; CHECK-NEXT: st.param.b32 [func_retval0], %r1; -; CHECK-NEXT: ret; +; CHECK-NOF32X2-LABEL: test_extract_0( +; CHECK-NOF32X2: { +; CHECK-NOF32X2-NEXT: .reg .b32 %r<2>; +; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-NOF32X2-EMPTY: +; CHECK-NOF32X2-NEXT: // %bb.0: +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_extract_0_param_0]; +; CHECK-NOF32X2-NEXT: { .reg .b32 tmp; mov.b64 {%r1, tmp}, %rd1; } +; CHECK-NOF32X2-NEXT: st.param.b32 [func_retval0], %r1; +; CHECK-NOF32X2-NEXT: ret; +; +; CHECK-F32X2-LABEL: test_extract_0( +; CHECK-F32X2: { +; CHECK-F32X2-NEXT: .reg .b32 %r<2>; +; CHECK-F32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-F32X2-EMPTY: +; CHECK-F32X2-NEXT: // %bb.0: +; CHECK-F32X2-NEXT: ld.param.b64 %rd1, [test_extract_0_param_0]; +; CHECK-F32X2-NEXT: mov.b64 {%r1, _}, %rd1; +; CHECK-F32X2-NEXT: st.param.b32 [func_retval0], %r1; +; CHECK-F32X2-NEXT: ret; %e = extractelement <2 x float> %a, i32 0 ret float %e } define float @test_extract_1(<2 x float> %a) #0 { -; CHECK-LABEL: test_extract_1( -; CHECK: { -; CHECK-NEXT: .reg .b32 %r<3>; -; CHECK-NEXT: .reg .b64 %rd<2>; -; CHECK-EMPTY: -; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_extract_1_param_0]; -; CHECK-NEXT: st.param.b32 [func_retval0], %r2; -; CHECK-NEXT: ret; +; CHECK-NOF32X2-LABEL: test_extract_1( +; CHECK-NOF32X2: { +; CHECK-NOF32X2-NEXT: .reg .b32 %r<2>; +; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-NOF32X2-EMPTY: +; CHECK-NOF32X2-NEXT: // %bb.0: +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_extract_1_param_0]; +; CHECK-NOF32X2-NEXT: { .reg .b32 tmp; mov.b64 {tmp, %r1}, %rd1; } +; CHECK-NOF32X2-NEXT: st.param.b32 [func_retval0], %r1; +; CHECK-NOF32X2-NEXT: ret; +; +; CHECK-F32X2-LABEL: test_extract_1( +; CHECK-F32X2: { +; CHECK-F32X2-NEXT: .reg .b32 %r<2>; +; CHECK-F32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-F32X2-EMPTY: +; CHECK-F32X2-NEXT: // %bb.0: +; CHECK-F32X2-NEXT: ld.param.b64 %rd1, [test_extract_1_param_0]; +; CHECK-F32X2-NEXT: mov.b64 {_, %r1}, %rd1; +; CHECK-F32X2-NEXT: st.param.b32 [func_retval0], %r1; +; CHECK-F32X2-NEXT: ret; %e = extractelement <2 x float> %a, i32 1 ret float %e } @@ -70,10 +94,12 @@ define <2 x float> @test_fadd(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fadd_param_1]; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fadd_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -98,7 +124,8 @@ define <2 x float> @test_fadd_imm_0(<2 x float> %a) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_imm_0_param_0]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_imm_0_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r3, %r2, 0f40000000; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r4, %r1, 0f3F800000; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -128,7 +155,8 @@ define <2 x float> @test_fadd_imm_1(<2 x float> %a) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_imm_1_param_0]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_imm_1_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r3, %r2, 0f40000000; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r4, %r1, 0f3F800000; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -158,13 +186,17 @@ define <4 x float> @test_fadd_v4(<4 x float> %a, <4 x float> %b) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<5>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_v4_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [test_fadd_v4_param_1]; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r9, %r4, %r8; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r10, %r3, %r7; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r11, %r2, %r6; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r12, %r1, %r5; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r12, %r11, %r10, %r9}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [test_fadd_v4_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_v4_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r6, %r3, %r1; +; CHECK-NOF32X2-NEXT: mov.b64 {%r7, %r8}, %rd3; +; CHECK-NOF32X2-NEXT: mov.b64 {%r9, %r10}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r11, %r10, %r8; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r12, %r9, %r7; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r12, %r11, %r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_v4( @@ -189,12 +221,14 @@ define <4 x float> @test_fadd_imm_0_v4(<4 x float> %a) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_imm_0_v4_param_0]; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r5, %r4, 0f40800000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r6, %r3, 0f40400000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r7, %r2, 0f40000000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r8, %r1, 0f3F800000; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r6, %r5}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_imm_0_v4_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r3, %r2, 0f40800000; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r4, %r1, 0f40400000; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r7, %r6, 0f40000000; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r8, %r5, 0f3F800000; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r4, %r3}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_imm_0_v4( @@ -225,12 +259,14 @@ define <4 x float> @test_fadd_imm_1_v4(<4 x float> %a) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_imm_1_v4_param_0]; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r5, %r4, 0f40800000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r6, %r3, 0f40400000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r7, %r2, 0f40000000; -; CHECK-NOF32X2-NEXT: add.rn.f32 %r8, %r1, 0f3F800000; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r6, %r5}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_imm_1_v4_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r3, %r2, 0f40800000; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r4, %r1, 0f40400000; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r7, %r6, 0f40000000; +; CHECK-NOF32X2-NEXT: add.rn.f32 %r8, %r5, 0f3F800000; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r4, %r3}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_imm_1_v4( @@ -261,10 +297,12 @@ define <2 x float> @test_fsub(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fsub_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fsub_param_1]; -; CHECK-NOF32X2-NEXT: sub.rn.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: sub.rn.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fsub_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fsub_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: sub.rn.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: sub.rn.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -289,7 +327,8 @@ define <2 x float> @test_fneg(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fneg_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fneg_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: neg.f32 %r3, %r2; ; CHECK-NEXT: neg.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -305,10 +344,12 @@ define <2 x float> @test_fmul(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fmul_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fmul_param_1]; -; CHECK-NOF32X2-NEXT: mul.rn.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: mul.rn.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fmul_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fmul_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: mul.rn.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: mul.rn.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -333,10 +374,12 @@ define <2 x float> @test_fdiv(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fdiv_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fdiv_param_1]; -; CHECK-NEXT: div.rn.f32 %r5, %r2, %r4; -; CHECK-NEXT: div.rn.f32 %r6, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fdiv_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fdiv_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: div.rn.f32 %r5, %r4, %r2; +; CHECK-NEXT: div.rn.f32 %r6, %r3, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NEXT: ret; %r = fdiv <2 x float> %a, %b @@ -351,20 +394,22 @@ define <2 x float> @test_frem(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_frem_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_frem_param_1]; -; CHECK-NEXT: div.rn.f32 %r5, %r2, %r4; +; CHECK-NEXT: ld.param.b64 %rd2, [test_frem_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_frem_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: div.rn.f32 %r5, %r4, %r2; ; CHECK-NEXT: cvt.rzi.f32.f32 %r6, %r5; ; CHECK-NEXT: neg.f32 %r7, %r6; -; CHECK-NEXT: fma.rn.f32 %r8, %r7, %r4, %r2; -; CHECK-NEXT: testp.infinite.f32 %p1, %r4; -; CHECK-NEXT: selp.f32 %r9, %r2, %r8, %p1; -; CHECK-NEXT: div.rn.f32 %r10, %r1, %r3; +; CHECK-NEXT: fma.rn.f32 %r8, %r7, %r2, %r4; +; CHECK-NEXT: testp.infinite.f32 %p1, %r2; +; CHECK-NEXT: selp.f32 %r9, %r4, %r8, %p1; +; CHECK-NEXT: div.rn.f32 %r10, %r3, %r1; ; CHECK-NEXT: cvt.rzi.f32.f32 %r11, %r10; ; CHECK-NEXT: neg.f32 %r12, %r11; -; CHECK-NEXT: fma.rn.f32 %r13, %r12, %r3, %r1; -; CHECK-NEXT: testp.infinite.f32 %p2, %r3; -; CHECK-NEXT: selp.f32 %r14, %r1, %r13, %p2; +; CHECK-NEXT: fma.rn.f32 %r13, %r12, %r1, %r3; +; CHECK-NEXT: testp.infinite.f32 %p2, %r1; +; CHECK-NEXT: selp.f32 %r14, %r3, %r13, %p2; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r14, %r9}; ; CHECK-NEXT: ret; %r = frem <2 x float> %a, %b @@ -378,10 +423,12 @@ define <2 x float> @test_fadd_ftz(<2 x float> %a, <2 x float> %b) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_ftz_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fadd_ftz_param_1]; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fadd_ftz_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -406,7 +453,8 @@ define <2 x float> @test_fadd_imm_0_ftz(<2 x float> %a) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_imm_0_ftz_param_0]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_imm_0_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r3, %r2, 0f40000000; ; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r4, %r1, 0f3F800000; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -436,7 +484,8 @@ define <2 x float> @test_fadd_imm_1_ftz(<2 x float> %a) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fadd_imm_1_ftz_param_0]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fadd_imm_1_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r3, %r2, 0f40000000; ; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r4, %r1, 0f3F800000; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -466,13 +515,17 @@ define <4 x float> @test_fadd_v4_ftz(<4 x float> %a, <4 x float> %b) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<5>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_v4_ftz_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [test_fadd_v4_ftz_param_1]; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r9, %r4, %r8; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r10, %r3, %r7; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r11, %r2, %r6; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r12, %r1, %r5; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r12, %r11, %r10, %r9}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [test_fadd_v4_ftz_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_v4_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r6, %r3, %r1; +; CHECK-NOF32X2-NEXT: mov.b64 {%r7, %r8}, %rd3; +; CHECK-NOF32X2-NEXT: mov.b64 {%r9, %r10}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r11, %r10, %r8; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r12, %r9, %r7; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r12, %r11, %r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_v4_ftz( @@ -497,12 +550,14 @@ define <4 x float> @test_fadd_imm_0_v4_ftz(<4 x float> %a) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_imm_0_v4_ftz_param_0]; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r5, %r4, 0f40800000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r6, %r3, 0f40400000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r7, %r2, 0f40000000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r8, %r1, 0f3F800000; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r6, %r5}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_imm_0_v4_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r3, %r2, 0f40800000; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r4, %r1, 0f40400000; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r7, %r6, 0f40000000; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r8, %r5, 0f3F800000; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r4, %r3}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_imm_0_v4_ftz( @@ -533,12 +588,14 @@ define <4 x float> @test_fadd_imm_1_v4_ftz(<4 x float> %a) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [test_fadd_imm_1_v4_ftz_param_0]; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r5, %r4, 0f40800000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r6, %r3, 0f40400000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r7, %r2, 0f40000000; -; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r8, %r1, 0f3F800000; -; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r6, %r5}; +; CHECK-NOF32X2-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_fadd_imm_1_v4_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r3, %r2, 0f40800000; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r4, %r1, 0f40400000; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r7, %r6, 0f40000000; +; CHECK-NOF32X2-NEXT: add.rn.ftz.f32 %r8, %r5, 0f3F800000; +; CHECK-NOF32X2-NEXT: st.param.v4.b32 [func_retval0], {%r8, %r7, %r4, %r3}; ; CHECK-NOF32X2-NEXT: ret; ; ; CHECK-F32X2-LABEL: test_fadd_imm_1_v4_ftz( @@ -569,10 +626,12 @@ define <2 x float> @test_fsub_ftz(<2 x float> %a, <2 x float> %b) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fsub_ftz_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fsub_ftz_param_1]; -; CHECK-NOF32X2-NEXT: sub.rn.ftz.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: sub.rn.ftz.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fsub_ftz_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fsub_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: sub.rn.ftz.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: sub.rn.ftz.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -597,7 +656,8 @@ define <2 x float> @test_fneg_ftz(<2 x float> %a) #2 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fneg_ftz_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fneg_ftz_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: neg.ftz.f32 %r3, %r2; ; CHECK-NEXT: neg.ftz.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -613,10 +673,12 @@ define <2 x float> @test_fmul_ftz(<2 x float> %a, <2 x float> %b) #2 { ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<3>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fmul_ftz_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fmul_ftz_param_1]; -; CHECK-NOF32X2-NEXT: mul.rn.ftz.f32 %r5, %r2, %r4; -; CHECK-NOF32X2-NEXT: mul.rn.ftz.f32 %r6, %r1, %r3; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fmul_ftz_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fmul_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NOF32X2-NEXT: mul.rn.ftz.f32 %r5, %r4, %r2; +; CHECK-NOF32X2-NEXT: mul.rn.ftz.f32 %r6, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -641,11 +703,14 @@ define <2 x float> @test_fma_ftz(<2 x float> %a, <2 x float> %b, <2 x float> %c) ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<4>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fma_ftz_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fma_ftz_param_1]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_fma_ftz_param_2]; -; CHECK-NOF32X2-NEXT: fma.rn.ftz.f32 %r7, %r2, %r4, %r6; -; CHECK-NOF32X2-NEXT: fma.rn.ftz.f32 %r8, %r1, %r3, %r5; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd3, [test_fma_ftz_param_2]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fma_ftz_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fma_ftz_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd3; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: fma.rn.ftz.f32 %r7, %r6, %r4, %r2; +; CHECK-NOF32X2-NEXT: fma.rn.ftz.f32 %r8, %r5, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -671,10 +736,12 @@ define <2 x float> @test_fdiv_ftz(<2 x float> %a, <2 x float> %b) #2 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fdiv_ftz_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fdiv_ftz_param_1]; -; CHECK-NEXT: div.rn.ftz.f32 %r5, %r2, %r4; -; CHECK-NEXT: div.rn.ftz.f32 %r6, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fdiv_ftz_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fdiv_ftz_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: div.rn.ftz.f32 %r5, %r4, %r2; +; CHECK-NEXT: div.rn.ftz.f32 %r6, %r3, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NEXT: ret; %r = fdiv <2 x float> %a, %b @@ -689,20 +756,22 @@ define <2 x float> @test_frem_ftz(<2 x float> %a, <2 x float> %b) #2 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_frem_ftz_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_frem_ftz_param_1]; -; CHECK-NEXT: div.rn.ftz.f32 %r5, %r2, %r4; +; CHECK-NEXT: ld.param.b64 %rd2, [test_frem_ftz_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_frem_ftz_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: div.rn.ftz.f32 %r5, %r4, %r2; ; CHECK-NEXT: cvt.rzi.ftz.f32.f32 %r6, %r5; ; CHECK-NEXT: neg.ftz.f32 %r7, %r6; -; CHECK-NEXT: fma.rn.ftz.f32 %r8, %r7, %r4, %r2; -; CHECK-NEXT: testp.infinite.f32 %p1, %r4; -; CHECK-NEXT: selp.f32 %r9, %r2, %r8, %p1; -; CHECK-NEXT: div.rn.ftz.f32 %r10, %r1, %r3; +; CHECK-NEXT: fma.rn.ftz.f32 %r8, %r7, %r2, %r4; +; CHECK-NEXT: testp.infinite.f32 %p1, %r2; +; CHECK-NEXT: selp.f32 %r9, %r4, %r8, %p1; +; CHECK-NEXT: div.rn.ftz.f32 %r10, %r3, %r1; ; CHECK-NEXT: cvt.rzi.ftz.f32.f32 %r11, %r10; ; CHECK-NEXT: neg.ftz.f32 %r12, %r11; -; CHECK-NEXT: fma.rn.ftz.f32 %r13, %r12, %r3, %r1; -; CHECK-NEXT: testp.infinite.f32 %p2, %r3; -; CHECK-NEXT: selp.f32 %r14, %r1, %r13, %p2; +; CHECK-NEXT: fma.rn.ftz.f32 %r13, %r12, %r1, %r3; +; CHECK-NEXT: testp.infinite.f32 %p2, %r1; +; CHECK-NEXT: selp.f32 %r14, %r3, %r13, %p2; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r14, %r9}; ; CHECK-NEXT: ret; %r = frem <2 x float> %a, %b @@ -877,14 +946,18 @@ define <2 x float> @test_select_cc(<2 x float> %a, <2 x float> %b, <2 x float> % ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_select_cc_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_param_2]; -; CHECK-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_select_cc_param_3]; -; CHECK-NEXT: setp.neu.f32 %p1, %r3, %r5; -; CHECK-NEXT: setp.neu.f32 %p2, %r4, %r6; -; CHECK-NEXT: ld.param.v2.b32 {%r7, %r8}, [test_select_cc_param_1]; -; CHECK-NEXT: selp.f32 %r9, %r2, %r8, %p2; -; CHECK-NEXT: selp.f32 %r10, %r1, %r7, %p1; +; CHECK-NEXT: ld.param.b64 %rd4, [test_select_cc_param_3]; +; CHECK-NEXT: ld.param.b64 %rd3, [test_select_cc_param_2]; +; CHECK-NEXT: ld.param.b64 %rd2, [test_select_cc_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_select_cc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd3; +; CHECK-NEXT: setp.neu.f32 %p1, %r3, %r1; +; CHECK-NEXT: setp.neu.f32 %p2, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r5, %r6}, %rd2; +; CHECK-NEXT: mov.b64 {%r7, %r8}, %rd1; +; CHECK-NEXT: selp.f32 %r9, %r8, %r6, %p2; +; CHECK-NEXT: selp.f32 %r10, %r7, %r5, %p1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r10, %r9}; ; CHECK-NEXT: ret; %cc = fcmp une <2 x float> %c, %d @@ -902,10 +975,12 @@ define <2 x double> @test_select_cc_f64_f32(<2 x double> %a, <2 x double> %b, <2 ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [test_select_cc_f64_f32_param_1]; ; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [test_select_cc_f64_f32_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_select_cc_f64_f32_param_2]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_f64_f32_param_3]; -; CHECK-NEXT: setp.neu.f32 %p1, %r1, %r3; -; CHECK-NEXT: setp.neu.f32 %p2, %r2, %r4; +; CHECK-NEXT: ld.param.b64 %rd6, [test_select_cc_f64_f32_param_3]; +; CHECK-NEXT: ld.param.b64 %rd5, [test_select_cc_f64_f32_param_2]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd6; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd5; +; CHECK-NEXT: setp.neu.f32 %p1, %r3, %r1; +; CHECK-NEXT: setp.neu.f32 %p2, %r4, %r2; ; CHECK-NEXT: selp.f64 %rd7, %rd2, %rd4, %p2; ; CHECK-NEXT: selp.f64 %rd8, %rd1, %rd3, %p1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd8, %rd7}; @@ -925,12 +1000,14 @@ define <2 x float> @test_select_cc_f32_f64(<2 x float> %a, <2 x float> %b, <2 x ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.v2.b64 {%rd5, %rd6}, [test_select_cc_f32_f64_param_3]; ; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [test_select_cc_f32_f64_param_2]; -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_select_cc_f32_f64_param_0]; +; CHECK-NEXT: ld.param.b64 %rd2, [test_select_cc_f32_f64_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_select_cc_f32_f64_param_0]; ; CHECK-NEXT: setp.neu.f64 %p1, %rd3, %rd5; ; CHECK-NEXT: setp.neu.f64 %p2, %rd4, %rd6; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_f32_f64_param_1]; -; CHECK-NEXT: selp.f32 %r5, %r2, %r4, %p2; -; CHECK-NEXT: selp.f32 %r6, %r1, %r3, %p1; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: selp.f32 %r5, %r4, %r2, %p2; +; CHECK-NEXT: selp.f32 %r6, %r3, %r1, %p1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NEXT: ret; %cc = fcmp une <2 x double> %c, %d @@ -947,10 +1024,12 @@ define <2 x i1> @test_fcmp_une(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_une_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_une_param_1]; -; CHECK-NEXT: setp.neu.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.neu.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_une_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_une_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.neu.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.neu.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -969,10 +1048,12 @@ define <2 x i1> @test_fcmp_ueq(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ueq_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ueq_param_1]; -; CHECK-NEXT: setp.equ.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.equ.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ueq_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ueq_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.equ.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.equ.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -991,10 +1072,12 @@ define <2 x i1> @test_fcmp_ugt(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ugt_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ugt_param_1]; -; CHECK-NEXT: setp.gtu.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.gtu.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ugt_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ugt_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.gtu.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.gtu.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1013,10 +1096,12 @@ define <2 x i1> @test_fcmp_uge(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_uge_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_uge_param_1]; -; CHECK-NEXT: setp.geu.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.geu.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_uge_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_uge_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.geu.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.geu.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1035,10 +1120,12 @@ define <2 x i1> @test_fcmp_ult(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ult_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ult_param_1]; -; CHECK-NEXT: setp.ltu.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.ltu.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ult_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ult_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.ltu.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.ltu.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1057,10 +1144,12 @@ define <2 x i1> @test_fcmp_ule(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ule_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ule_param_1]; -; CHECK-NEXT: setp.leu.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.leu.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ule_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ule_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.leu.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.leu.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1079,10 +1168,12 @@ define <2 x i1> @test_fcmp_uno(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_uno_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_uno_param_1]; -; CHECK-NEXT: setp.nan.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.nan.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_uno_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_uno_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.nan.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.nan.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1101,10 +1192,12 @@ define <2 x i1> @test_fcmp_one(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_one_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_one_param_1]; -; CHECK-NEXT: setp.ne.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.ne.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_one_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_one_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.ne.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.ne.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1123,10 +1216,12 @@ define <2 x i1> @test_fcmp_oeq(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_oeq_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_oeq_param_1]; -; CHECK-NEXT: setp.eq.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.eq.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_oeq_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_oeq_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.eq.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.eq.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1145,10 +1240,12 @@ define <2 x i1> @test_fcmp_ogt(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ogt_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ogt_param_1]; -; CHECK-NEXT: setp.gt.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.gt.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ogt_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ogt_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.gt.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.gt.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1167,10 +1264,12 @@ define <2 x i1> @test_fcmp_oge(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_oge_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_oge_param_1]; -; CHECK-NEXT: setp.ge.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.ge.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_oge_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_oge_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.ge.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.ge.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1189,10 +1288,12 @@ define <2 x i1> @test_fcmp_olt(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_olt_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_olt_param_1]; -; CHECK-NEXT: setp.lt.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.lt.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_olt_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_olt_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.lt.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.lt.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1211,10 +1312,12 @@ define <2 x i1> @test_fcmp_ole(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ole_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ole_param_1]; -; CHECK-NEXT: setp.le.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.le.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ole_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ole_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.le.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.le.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1233,10 +1336,12 @@ define <2 x i1> @test_fcmp_ord(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fcmp_ord_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fcmp_ord_param_1]; -; CHECK-NEXT: setp.num.f32 %p1, %r2, %r4; -; CHECK-NEXT: setp.num.f32 %p2, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_fcmp_ord_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fcmp_ord_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: setp.num.f32 %p1, %r4, %r2; +; CHECK-NEXT: setp.num.f32 %p2, %r3, %r1; ; CHECK-NEXT: selp.b16 %rs1, -1, 0, %p2; ; CHECK-NEXT: st.param.b8 [func_retval0], %rs1; ; CHECK-NEXT: selp.b16 %rs2, -1, 0, %p1; @@ -1253,7 +1358,8 @@ define <2 x i32> @test_fptosi_i32(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptosi_i32_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fptosi_i32_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rzi.s32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rzi.s32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1269,7 +1375,8 @@ define <2 x i64> @test_fptosi_i64(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptosi_i64_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fptosi_i64_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rzi.s64.f32 %rd2, %r2; ; CHECK-NEXT: cvt.rzi.s64.f32 %rd3, %r1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd3, %rd2}; @@ -1285,7 +1392,8 @@ define <2 x i32> @test_fptoui_2xi32(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptoui_2xi32_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fptoui_2xi32_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rzi.u32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rzi.u32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1301,7 +1409,8 @@ define <2 x i64> @test_fptoui_2xi64(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptoui_2xi64_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fptoui_2xi64_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rzi.u64.f32 %rd2, %r2; ; CHECK-NEXT: cvt.rzi.u64.f32 %rd3, %r1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd3, %rd2}; @@ -1380,9 +1489,10 @@ define <2 x float> @test_uitofp_2xi32_fadd(<2 x i32> %a, <2 x float> %b) #0 { ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: ; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_uitofp_2xi32_fadd_param_0]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_uitofp_2xi32_fadd_param_1]; ; CHECK-NOF32X2-NEXT: cvt.rn.f32.u32 %r3, %r1; ; CHECK-NOF32X2-NEXT: cvt.rn.f32.u32 %r4, %r2; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_uitofp_2xi32_fadd_param_1]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r7, %r6, %r4; ; CHECK-NOF32X2-NEXT: add.rn.f32 %r8, %r5, %r3; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; @@ -1431,7 +1541,8 @@ define <2 x double> @test_fpext_2xdouble(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<4>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fpext_2xdouble_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fpext_2xdouble_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.f64.f32 %rd2, %r2; ; CHECK-NEXT: cvt.f64.f32 %rd3, %r1; ; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd3, %rd2}; @@ -1499,7 +1610,8 @@ define <2 x float> @test_sqrt(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_sqrt_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_sqrt_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: sqrt.rn.f32 %r3, %r2; ; CHECK-NEXT: sqrt.rn.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1522,7 +1634,8 @@ define <2 x float> @test_sin(<2 x float> %a) #0 #1 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_sin_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_sin_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: sin.approx.f32 %r3, %r2; ; CHECK-NEXT: sin.approx.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1538,7 +1651,8 @@ define <2 x float> @test_cos(<2 x float> %a) #0 #1 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_cos_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_cos_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cos.approx.f32 %r3, %r2; ; CHECK-NEXT: cos.approx.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1597,11 +1711,14 @@ define <2 x float> @test_fma(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<4>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fma_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fma_param_1]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_fma_param_2]; -; CHECK-NOF32X2-NEXT: fma.rn.f32 %r7, %r2, %r4, %r6; -; CHECK-NOF32X2-NEXT: fma.rn.f32 %r8, %r1, %r3, %r5; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd3, [test_fma_param_2]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fma_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fma_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd3; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: fma.rn.f32 %r7, %r6, %r4, %r2; +; CHECK-NOF32X2-NEXT: fma.rn.f32 %r8, %r5, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -1627,7 +1744,8 @@ define <2 x float> @test_fabs(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fabs_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_fabs_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: abs.f32 %r3, %r2; ; CHECK-NEXT: abs.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1643,10 +1761,12 @@ define <2 x float> @test_minnum(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_minnum_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_minnum_param_1]; -; CHECK-NEXT: min.f32 %r5, %r2, %r4; -; CHECK-NEXT: min.f32 %r6, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_minnum_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_minnum_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: min.f32 %r5, %r4, %r2; +; CHECK-NEXT: min.f32 %r6, %r3, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NEXT: ret; %r = call <2 x float> @llvm.minnum(<2 x float> %a, <2 x float> %b) @@ -1660,10 +1780,12 @@ define <2 x float> @test_maxnum(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_maxnum_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_maxnum_param_1]; -; CHECK-NEXT: max.f32 %r5, %r2, %r4; -; CHECK-NEXT: max.f32 %r6, %r1, %r3; +; CHECK-NEXT: ld.param.b64 %rd2, [test_maxnum_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_maxnum_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd2; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd1; +; CHECK-NEXT: max.f32 %r5, %r4, %r2; +; CHECK-NEXT: max.f32 %r6, %r3, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; ; CHECK-NEXT: ret; %r = call <2 x float> @llvm.maxnum(<2 x float> %a, <2 x float> %b) @@ -1677,8 +1799,10 @@ define <2 x float> @test_copysign(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<3>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_copysign_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_copysign_param_1]; +; CHECK-NEXT: ld.param.b64 %rd2, [test_copysign_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_copysign_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; ; CHECK-NEXT: copysign.f32 %r5, %r4, %r2; ; CHECK-NEXT: copysign.f32 %r6, %r3, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r6, %r5}; @@ -1696,18 +1820,19 @@ define <2 x float> @test_copysign_f64(<2 x float> %a, <2 x double> %b) #0 { ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.v2.b64 {%rd2, %rd3}, [test_copysign_f64_param_1]; -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_copysign_f64_param_0]; -; CHECK-NEXT: abs.f32 %r3, %r2; -; CHECK-NEXT: neg.f32 %r4, %r3; +; CHECK-NEXT: ld.param.b64 %rd1, [test_copysign_f64_param_0]; ; CHECK-NEXT: shr.u64 %rd4, %rd3, 63; ; CHECK-NEXT: and.b64 %rd5, %rd4, 1; ; CHECK-NEXT: setp.ne.b64 %p1, %rd5, 0; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; +; CHECK-NEXT: abs.f32 %r3, %r2; +; CHECK-NEXT: neg.f32 %r4, %r3; ; CHECK-NEXT: selp.f32 %r5, %r4, %r3, %p1; -; CHECK-NEXT: abs.f32 %r6, %r1; -; CHECK-NEXT: neg.f32 %r7, %r6; ; CHECK-NEXT: shr.u64 %rd6, %rd2, 63; ; CHECK-NEXT: and.b64 %rd7, %rd6, 1; ; CHECK-NEXT: setp.ne.b64 %p2, %rd7, 0; +; CHECK-NEXT: abs.f32 %r6, %r1; +; CHECK-NEXT: neg.f32 %r7, %r6; ; CHECK-NEXT: selp.f32 %r8, %r7, %r6, %p2; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r5}; ; CHECK-NEXT: ret; @@ -1723,8 +1848,10 @@ define <2 x double> @test_copysign_extended(<2 x float> %a, <2 x float> %b) #0 { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_copysign_extended_param_0]; -; CHECK-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_copysign_extended_param_1]; +; CHECK-NEXT: ld.param.b64 %rd2, [test_copysign_extended_param_1]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_copysign_extended_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; ; CHECK-NEXT: copysign.f32 %r5, %r3, %r1; ; CHECK-NEXT: copysign.f32 %r6, %r4, %r2; ; CHECK-NEXT: cvt.f64.f32 %rd3, %r6; @@ -1743,7 +1870,8 @@ define <2 x float> @test_floor(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_floor_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_floor_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rmi.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rmi.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1759,7 +1887,8 @@ define <2 x float> @test_ceil(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_ceil_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_ceil_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rpi.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rpi.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1775,7 +1904,8 @@ define <2 x float> @test_trunc(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_trunc_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_trunc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rzi.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rzi.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1791,7 +1921,8 @@ define <2 x float> @test_rint(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_rint_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_rint_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rni.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rni.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1807,7 +1938,8 @@ define <2 x float> @test_nearbyint(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_nearbyint_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_nearbyint_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rni.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rni.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1823,7 +1955,8 @@ define <2 x float> @test_roundeven(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_roundeven_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_roundeven_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: cvt.rni.f32.f32 %r3, %r2; ; CHECK-NEXT: cvt.rni.f32.f32 %r4, %r1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r4, %r3}; @@ -1841,7 +1974,8 @@ define <2 x float> @test_round(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_round_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_round_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: and.b32 %r3, %r2, -2147483648; ; CHECK-NEXT: or.b32 %r4, %r3, 1056964608; ; CHECK-NEXT: add.rn.f32 %r5, %r2, %r4; @@ -1875,11 +2009,14 @@ define <2 x float> @test_fmuladd(<2 x float> %a, <2 x float> %b, <2 x float> %c) ; CHECK-NOF32X2-NEXT: .reg .b64 %rd<4>; ; CHECK-NOF32X2-EMPTY: ; CHECK-NOF32X2-NEXT: // %bb.0: -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fmuladd_param_0]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_fmuladd_param_1]; -; CHECK-NOF32X2-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_fmuladd_param_2]; -; CHECK-NOF32X2-NEXT: fma.rn.f32 %r7, %r2, %r4, %r6; -; CHECK-NOF32X2-NEXT: fma.rn.f32 %r8, %r1, %r3, %r5; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd3, [test_fmuladd_param_2]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd2, [test_fmuladd_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_fmuladd_param_0]; +; CHECK-NOF32X2-NEXT: mov.b64 {%r1, %r2}, %rd3; +; CHECK-NOF32X2-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NOF32X2-NEXT: mov.b64 {%r5, %r6}, %rd1; +; CHECK-NOF32X2-NEXT: fma.rn.f32 %r7, %r6, %r4, %r2; +; CHECK-NOF32X2-NEXT: fma.rn.f32 %r8, %r5, %r3, %r1; ; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; ; CHECK-NOF32X2-NEXT: ret; ; @@ -1905,7 +2042,8 @@ define <2 x float> @test_shufflevector(<2 x float> %a) #0 { ; CHECK-NEXT: .reg .b64 %rd<2>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_shufflevector_param_0]; +; CHECK-NEXT: ld.param.b64 %rd1, [test_shufflevector_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd1; ; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r2, %r1}; ; CHECK-NEXT: ret; %s = shufflevector <2 x float> %a, <2 x float> poison, <2 x i32> @@ -1913,16 +2051,29 @@ define <2 x float> @test_shufflevector(<2 x float> %a) #0 { } define <2 x float> @test_insertelement(<2 x float> %a, float %x) #0 { -; CHECK-LABEL: test_insertelement( -; CHECK: { -; CHECK-NEXT: .reg .b32 %r<4>; -; CHECK-NEXT: .reg .b64 %rd<2>; -; CHECK-EMPTY: -; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.b32 %r1, [test_insertelement_param_1]; -; CHECK-NEXT: ld.param.v2.b32 {%r2, %r3}, [test_insertelement_param_0]; -; CHECK-NEXT: st.param.v2.b32 [func_retval0], {%r2, %r1}; -; CHECK-NEXT: ret; +; CHECK-NOF32X2-LABEL: test_insertelement( +; CHECK-NOF32X2: { +; CHECK-NOF32X2-NEXT: .reg .b32 %r<3>; +; CHECK-NOF32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-NOF32X2-EMPTY: +; CHECK-NOF32X2-NEXT: // %bb.0: +; CHECK-NOF32X2-NEXT: ld.param.b32 %r1, [test_insertelement_param_1]; +; CHECK-NOF32X2-NEXT: ld.param.b64 %rd1, [test_insertelement_param_0]; +; CHECK-NOF32X2-NEXT: { .reg .b32 tmp; mov.b64 {%r2, tmp}, %rd1; } +; CHECK-NOF32X2-NEXT: st.param.v2.b32 [func_retval0], {%r2, %r1}; +; CHECK-NOF32X2-NEXT: ret; +; +; CHECK-F32X2-LABEL: test_insertelement( +; CHECK-F32X2: { +; CHECK-F32X2-NEXT: .reg .b32 %r<3>; +; CHECK-F32X2-NEXT: .reg .b64 %rd<2>; +; CHECK-F32X2-EMPTY: +; CHECK-F32X2-NEXT: // %bb.0: +; CHECK-F32X2-NEXT: ld.param.b32 %r1, [test_insertelement_param_1]; +; CHECK-F32X2-NEXT: ld.param.b64 %rd1, [test_insertelement_param_0]; +; CHECK-F32X2-NEXT: mov.b64 {%r2, _}, %rd1; +; CHECK-F32X2-NEXT: st.param.v2.b32 [func_retval0], {%r2, %r1}; +; CHECK-F32X2-NEXT: ret; %i = insertelement <2 x float> %a, float %x, i64 1 ret <2 x float> %i } diff --git a/llvm/test/CodeGen/NVPTX/i1-select.ll b/llvm/test/CodeGen/NVPTX/i1-select.ll index f1adc3489c0d9..9a051b3fd8bb7 100644 --- a/llvm/test/CodeGen/NVPTX/i1-select.ll +++ b/llvm/test/CodeGen/NVPTX/i1-select.ll @@ -94,27 +94,27 @@ define i32 @test_select_i1_basic(i32 %v1, i32 %v2, i32 %v3, i32 %true, i32 %fals define i32 @test_select_i1_basic_folding(i32 %v1, i32 %v2, i32 %v3, i32 %true, i32 %false) { ; CHECK-LABEL: test_select_i1_basic_folding( ; CHECK: { -; CHECK-NEXT: .reg .pred %p<12>; -; CHECK-NEXT: .reg .b32 %r<9>; +; CHECK-NEXT: .reg .pred %p<13>; +; CHECK-NEXT: .reg .b32 %r<7>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: ld.param.b32 %r1, [test_select_i1_basic_folding_param_0]; ; CHECK-NEXT: setp.eq.b32 %p1, %r1, 0; -; CHECK-NEXT: ld.param.b32 %r3, [test_select_i1_basic_folding_param_1]; -; CHECK-NEXT: setp.ne.b32 %p2, %r3, 0; -; CHECK-NEXT: setp.eq.b32 %p3, %r3, 0; -; CHECK-NEXT: ld.param.b32 %r5, [test_select_i1_basic_folding_param_2]; -; CHECK-NEXT: setp.eq.b32 %p4, %r5, 0; -; CHECK-NEXT: ld.param.b32 %r6, [test_select_i1_basic_folding_param_3]; +; CHECK-NEXT: ld.param.b32 %r2, [test_select_i1_basic_folding_param_1]; +; CHECK-NEXT: setp.ne.b32 %p2, %r2, 0; +; CHECK-NEXT: setp.eq.b32 %p3, %r2, 0; +; CHECK-NEXT: ld.param.b32 %r3, [test_select_i1_basic_folding_param_2]; +; CHECK-NEXT: setp.eq.b32 %p4, %r3, 0; +; CHECK-NEXT: ld.param.b32 %r4, [test_select_i1_basic_folding_param_3]; ; CHECK-NEXT: xor.pred %p6, %p1, %p3; -; CHECK-NEXT: ld.param.b32 %r7, [test_select_i1_basic_folding_param_4]; +; CHECK-NEXT: ld.param.b32 %r5, [test_select_i1_basic_folding_param_4]; ; CHECK-NEXT: and.pred %p7, %p6, %p4; -; CHECK-NEXT: and.pred %p8, %p2, %p4; -; CHECK-NEXT: and.pred %p9, %p3, %p7; -; CHECK-NEXT: or.pred %p10, %p9, %p8; -; CHECK-NEXT: xor.pred %p11, %p10, %p3; -; CHECK-NEXT: selp.b32 %r8, %r6, %r7, %p11; -; CHECK-NEXT: st.param.b32 [func_retval0], %r8; +; CHECK-NEXT: and.pred %p9, %p2, %p4; +; CHECK-NEXT: and.pred %p10, %p3, %p7; +; CHECK-NEXT: or.pred %p11, %p10, %p9; +; CHECK-NEXT: xor.pred %p12, %p11, %p3; +; CHECK-NEXT: selp.b32 %r6, %r4, %r5, %p12; +; CHECK-NEXT: st.param.b32 [func_retval0], %r6; ; CHECK-NEXT: ret; %b1 = icmp eq i32 %v1, 0 %b2 = icmp eq i32 %v2, 0 diff --git a/llvm/test/CodeGen/NVPTX/i128.ll b/llvm/test/CodeGen/NVPTX/i128.ll index f2211eb1c0b8e..44d85589b5056 100644 --- a/llvm/test/CodeGen/NVPTX/i128.ll +++ b/llvm/test/CodeGen/NVPTX/i128.ll @@ -5,9 +5,9 @@ define i128 @srem_i128(i128 %lhs, i128 %rhs) { ; CHECK-LABEL: srem_i128( ; CHECK: { -; CHECK-NEXT: .reg .pred %p<22>; +; CHECK-NEXT: .reg .pred %p<20>; ; CHECK-NEXT: .reg .b32 %r<12>; -; CHECK-NEXT: .reg .b64 %rd<126>; +; CHECK-NEXT: .reg .b64 %rd<127>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: // %_udiv-special-cases ; CHECK-NEXT: ld.param.v2.b64 {%rd45, %rd46}, [srem_i128_param_0]; @@ -42,103 +42,102 @@ define i128 @srem_i128(i128 %lhs, i128 %rhs) { ; CHECK-NEXT: cvt.u64.u32 %rd62, %r4; ; CHECK-NEXT: add.s64 %rd63, %rd62, 64; ; CHECK-NEXT: selp.b64 %rd64, %rd61, %rd63, %p7; -; CHECK-NEXT: mov.b64 %rd116, 0; +; CHECK-NEXT: mov.b64 %rd117, 0; ; CHECK-NEXT: sub.cc.s64 %rd66, %rd60, %rd64; -; CHECK-NEXT: subc.cc.s64 %rd8, %rd116, 0; -; CHECK-NEXT: setp.ne.b64 %p8, %rd8, 0; -; CHECK-NEXT: and.pred %p10, %p8, %p8; -; CHECK-NEXT: setp.eq.b64 %p11, %rd8, 0; -; CHECK-NEXT: setp.gt.u64 %p12, %rd66, 127; -; CHECK-NEXT: and.pred %p13, %p11, %p12; -; CHECK-NEXT: or.pred %p14, %p13, %p10; -; CHECK-NEXT: or.pred %p15, %p5, %p14; -; CHECK-NEXT: xor.b64 %rd67, %rd66, 127; -; CHECK-NEXT: or.b64 %rd68, %rd67, %rd8; -; CHECK-NEXT: setp.eq.b64 %p16, %rd68, 0; -; CHECK-NEXT: selp.b64 %rd125, 0, %rd4, %p15; -; CHECK-NEXT: selp.b64 %rd124, 0, %rd3, %p15; -; CHECK-NEXT: or.pred %p17, %p15, %p16; -; CHECK-NEXT: @%p17 bra $L__BB0_5; +; CHECK-NEXT: subc.cc.s64 %rd67, %rd117, 0; +; CHECK-NEXT: setp.gt.u64 %p8, %rd66, 127; +; CHECK-NEXT: setp.eq.b64 %p9, %rd67, 0; +; CHECK-NEXT: and.pred %p10, %p9, %p8; +; CHECK-NEXT: setp.ne.b64 %p11, %rd67, 0; +; CHECK-NEXT: or.pred %p12, %p10, %p11; +; CHECK-NEXT: or.pred %p13, %p5, %p12; +; CHECK-NEXT: xor.b64 %rd68, %rd66, 127; +; CHECK-NEXT: or.b64 %rd69, %rd68, %rd67; +; CHECK-NEXT: setp.eq.b64 %p14, %rd69, 0; +; CHECK-NEXT: selp.b64 %rd126, 0, %rd4, %p13; +; CHECK-NEXT: selp.b64 %rd125, 0, %rd3, %p13; +; CHECK-NEXT: or.pred %p15, %p13, %p14; +; CHECK-NEXT: @%p15 bra $L__BB0_5; ; CHECK-NEXT: // %bb.3: // %udiv-bb1 -; CHECK-NEXT: add.cc.s64 %rd118, %rd66, 1; -; CHECK-NEXT: addc.cc.s64 %rd119, %rd8, 0; -; CHECK-NEXT: or.b64 %rd71, %rd118, %rd119; -; CHECK-NEXT: setp.eq.b64 %p18, %rd71, 0; +; CHECK-NEXT: add.cc.s64 %rd119, %rd66, 1; +; CHECK-NEXT: addc.cc.s64 %rd120, %rd67, 0; +; CHECK-NEXT: or.b64 %rd72, %rd119, %rd120; +; CHECK-NEXT: setp.eq.b64 %p16, %rd72, 0; ; CHECK-NEXT: cvt.u32.u64 %r5, %rd66; ; CHECK-NEXT: sub.s32 %r6, 127, %r5; -; CHECK-NEXT: shl.b64 %rd72, %rd4, %r6; +; CHECK-NEXT: shl.b64 %rd73, %rd4, %r6; ; CHECK-NEXT: sub.s32 %r7, 64, %r6; -; CHECK-NEXT: shr.u64 %rd73, %rd3, %r7; -; CHECK-NEXT: or.b64 %rd74, %rd72, %rd73; +; CHECK-NEXT: shr.u64 %rd74, %rd3, %r7; +; CHECK-NEXT: or.b64 %rd75, %rd73, %rd74; ; CHECK-NEXT: sub.s32 %r8, 63, %r5; -; CHECK-NEXT: shl.b64 %rd75, %rd3, %r8; -; CHECK-NEXT: setp.gt.s32 %p19, %r6, 63; -; CHECK-NEXT: selp.b64 %rd123, %rd75, %rd74, %p19; -; CHECK-NEXT: shl.b64 %rd122, %rd3, %r6; -; CHECK-NEXT: mov.b64 %rd113, %rd116; -; CHECK-NEXT: @%p18 bra $L__BB0_4; +; CHECK-NEXT: shl.b64 %rd76, %rd3, %r8; +; CHECK-NEXT: setp.gt.s32 %p17, %r6, 63; +; CHECK-NEXT: selp.b64 %rd124, %rd76, %rd75, %p17; +; CHECK-NEXT: shl.b64 %rd123, %rd3, %r6; +; CHECK-NEXT: mov.b64 %rd114, %rd117; +; CHECK-NEXT: @%p16 bra $L__BB0_4; ; CHECK-NEXT: // %bb.1: // %udiv-preheader -; CHECK-NEXT: cvt.u32.u64 %r9, %rd118; -; CHECK-NEXT: shr.u64 %rd78, %rd3, %r9; +; CHECK-NEXT: cvt.u32.u64 %r9, %rd119; +; CHECK-NEXT: shr.u64 %rd79, %rd3, %r9; ; CHECK-NEXT: sub.s32 %r10, 64, %r9; -; CHECK-NEXT: shl.b64 %rd79, %rd4, %r10; -; CHECK-NEXT: or.b64 %rd80, %rd78, %rd79; +; CHECK-NEXT: shl.b64 %rd80, %rd4, %r10; +; CHECK-NEXT: or.b64 %rd81, %rd79, %rd80; ; CHECK-NEXT: add.s32 %r11, %r9, -64; -; CHECK-NEXT: shr.u64 %rd81, %rd4, %r11; -; CHECK-NEXT: setp.gt.s32 %p20, %r9, 63; -; CHECK-NEXT: selp.b64 %rd120, %rd81, %rd80, %p20; -; CHECK-NEXT: shr.u64 %rd121, %rd4, %r9; +; CHECK-NEXT: shr.u64 %rd82, %rd4, %r11; +; CHECK-NEXT: setp.gt.s32 %p18, %r9, 63; +; CHECK-NEXT: selp.b64 %rd121, %rd82, %rd81, %p18; +; CHECK-NEXT: shr.u64 %rd122, %rd4, %r9; ; CHECK-NEXT: add.cc.s64 %rd35, %rd5, -1; ; CHECK-NEXT: addc.cc.s64 %rd36, %rd6, -1; -; CHECK-NEXT: mov.b64 %rd113, 0; -; CHECK-NEXT: mov.b64 %rd116, %rd113; +; CHECK-NEXT: mov.b64 %rd114, 0; +; CHECK-NEXT: mov.b64 %rd117, %rd114; ; CHECK-NEXT: $L__BB0_2: // %udiv-do-while ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: shr.u64 %rd82, %rd120, 63; -; CHECK-NEXT: shl.b64 %rd83, %rd121, 1; -; CHECK-NEXT: or.b64 %rd84, %rd83, %rd82; -; CHECK-NEXT: shl.b64 %rd85, %rd120, 1; -; CHECK-NEXT: shr.u64 %rd86, %rd123, 63; -; CHECK-NEXT: or.b64 %rd87, %rd85, %rd86; -; CHECK-NEXT: shr.u64 %rd88, %rd122, 63; -; CHECK-NEXT: shl.b64 %rd89, %rd123, 1; -; CHECK-NEXT: or.b64 %rd90, %rd89, %rd88; -; CHECK-NEXT: shl.b64 %rd91, %rd122, 1; -; CHECK-NEXT: or.b64 %rd122, %rd116, %rd91; -; CHECK-NEXT: or.b64 %rd123, %rd113, %rd90; -; CHECK-NEXT: sub.cc.s64 %rd92, %rd35, %rd87; -; CHECK-NEXT: subc.cc.s64 %rd93, %rd36, %rd84; -; CHECK-NEXT: shr.s64 %rd94, %rd93, 63; -; CHECK-NEXT: and.b64 %rd116, %rd94, 1; -; CHECK-NEXT: and.b64 %rd95, %rd94, %rd5; -; CHECK-NEXT: and.b64 %rd96, %rd94, %rd6; -; CHECK-NEXT: sub.cc.s64 %rd120, %rd87, %rd95; -; CHECK-NEXT: subc.cc.s64 %rd121, %rd84, %rd96; -; CHECK-NEXT: add.cc.s64 %rd118, %rd118, -1; -; CHECK-NEXT: addc.cc.s64 %rd119, %rd119, -1; -; CHECK-NEXT: or.b64 %rd97, %rd118, %rd119; -; CHECK-NEXT: setp.eq.b64 %p21, %rd97, 0; -; CHECK-NEXT: @%p21 bra $L__BB0_4; +; CHECK-NEXT: shr.u64 %rd83, %rd121, 63; +; CHECK-NEXT: shl.b64 %rd84, %rd122, 1; +; CHECK-NEXT: or.b64 %rd85, %rd84, %rd83; +; CHECK-NEXT: shl.b64 %rd86, %rd121, 1; +; CHECK-NEXT: shr.u64 %rd87, %rd124, 63; +; CHECK-NEXT: or.b64 %rd88, %rd86, %rd87; +; CHECK-NEXT: shr.u64 %rd89, %rd123, 63; +; CHECK-NEXT: shl.b64 %rd90, %rd124, 1; +; CHECK-NEXT: or.b64 %rd91, %rd90, %rd89; +; CHECK-NEXT: shl.b64 %rd92, %rd123, 1; +; CHECK-NEXT: or.b64 %rd123, %rd117, %rd92; +; CHECK-NEXT: or.b64 %rd124, %rd114, %rd91; +; CHECK-NEXT: sub.cc.s64 %rd93, %rd35, %rd88; +; CHECK-NEXT: subc.cc.s64 %rd94, %rd36, %rd85; +; CHECK-NEXT: shr.s64 %rd95, %rd94, 63; +; CHECK-NEXT: and.b64 %rd117, %rd95, 1; +; CHECK-NEXT: and.b64 %rd96, %rd95, %rd5; +; CHECK-NEXT: and.b64 %rd97, %rd95, %rd6; +; CHECK-NEXT: sub.cc.s64 %rd121, %rd88, %rd96; +; CHECK-NEXT: subc.cc.s64 %rd122, %rd85, %rd97; +; CHECK-NEXT: add.cc.s64 %rd119, %rd119, -1; +; CHECK-NEXT: addc.cc.s64 %rd120, %rd120, -1; +; CHECK-NEXT: or.b64 %rd98, %rd119, %rd120; +; CHECK-NEXT: setp.eq.b64 %p19, %rd98, 0; +; CHECK-NEXT: @%p19 bra $L__BB0_4; ; CHECK-NEXT: bra.uni $L__BB0_2; ; CHECK-NEXT: $L__BB0_4: // %udiv-loop-exit -; CHECK-NEXT: shr.u64 %rd98, %rd122, 63; -; CHECK-NEXT: shl.b64 %rd99, %rd123, 1; -; CHECK-NEXT: or.b64 %rd100, %rd99, %rd98; -; CHECK-NEXT: shl.b64 %rd101, %rd122, 1; -; CHECK-NEXT: or.b64 %rd124, %rd116, %rd101; -; CHECK-NEXT: or.b64 %rd125, %rd113, %rd100; +; CHECK-NEXT: shr.u64 %rd99, %rd123, 63; +; CHECK-NEXT: shl.b64 %rd100, %rd124, 1; +; CHECK-NEXT: or.b64 %rd101, %rd100, %rd99; +; CHECK-NEXT: shl.b64 %rd102, %rd123, 1; +; CHECK-NEXT: or.b64 %rd125, %rd117, %rd102; +; CHECK-NEXT: or.b64 %rd126, %rd114, %rd101; ; CHECK-NEXT: $L__BB0_5: // %udiv-end -; CHECK-NEXT: mul.hi.u64 %rd102, %rd5, %rd124; -; CHECK-NEXT: mad.lo.s64 %rd103, %rd5, %rd125, %rd102; -; CHECK-NEXT: mad.lo.s64 %rd104, %rd6, %rd124, %rd103; -; CHECK-NEXT: mul.lo.s64 %rd105, %rd5, %rd124; -; CHECK-NEXT: sub.cc.s64 %rd106, %rd3, %rd105; -; CHECK-NEXT: subc.cc.s64 %rd107, %rd4, %rd104; -; CHECK-NEXT: xor.b64 %rd108, %rd106, %rd2; +; CHECK-NEXT: mul.hi.u64 %rd103, %rd5, %rd125; +; CHECK-NEXT: mad.lo.s64 %rd104, %rd5, %rd126, %rd103; +; CHECK-NEXT: mad.lo.s64 %rd105, %rd6, %rd125, %rd104; +; CHECK-NEXT: mul.lo.s64 %rd106, %rd5, %rd125; +; CHECK-NEXT: sub.cc.s64 %rd107, %rd3, %rd106; +; CHECK-NEXT: subc.cc.s64 %rd108, %rd4, %rd105; ; CHECK-NEXT: xor.b64 %rd109, %rd107, %rd2; -; CHECK-NEXT: sub.cc.s64 %rd110, %rd108, %rd2; -; CHECK-NEXT: subc.cc.s64 %rd111, %rd109, %rd2; -; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd110, %rd111}; +; CHECK-NEXT: xor.b64 %rd110, %rd108, %rd2; +; CHECK-NEXT: sub.cc.s64 %rd111, %rd109, %rd2; +; CHECK-NEXT: subc.cc.s64 %rd112, %rd110, %rd2; +; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd111, %rd112}; ; CHECK-NEXT: ret; %div = srem i128 %lhs, %rhs ret i128 %div @@ -149,7 +148,7 @@ define i128 @urem_i128(i128 %lhs, i128 %rhs) { ; CHECK: { ; CHECK-NEXT: .reg .pred %p<18>; ; CHECK-NEXT: .reg .b32 %r<12>; -; CHECK-NEXT: .reg .b64 %rd<111>; +; CHECK-NEXT: .reg .b64 %rd<113>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: // %_udiv-special-cases ; CHECK-NEXT: ld.param.v2.b64 {%rd41, %rd42}, [urem_i128_param_0]; @@ -173,98 +172,98 @@ define i128 @urem_i128(i128 %lhs, i128 %rhs) { ; CHECK-NEXT: cvt.u64.u32 %rd52, %r4; ; CHECK-NEXT: add.s64 %rd53, %rd52, 64; ; CHECK-NEXT: selp.b64 %rd54, %rd51, %rd53, %p5; -; CHECK-NEXT: mov.b64 %rd101, 0; -; CHECK-NEXT: sub.cc.s64 %rd5, %rd50, %rd54; -; CHECK-NEXT: subc.cc.s64 %rd6, %rd101, 0; -; CHECK-NEXT: setp.gt.u64 %p6, %rd5, 127; -; CHECK-NEXT: setp.eq.b64 %p7, %rd6, 0; +; CHECK-NEXT: mov.b64 %rd103, 0; +; CHECK-NEXT: sub.cc.s64 %rd56, %rd50, %rd54; +; CHECK-NEXT: subc.cc.s64 %rd57, %rd103, 0; +; CHECK-NEXT: setp.gt.u64 %p6, %rd56, 127; +; CHECK-NEXT: setp.eq.b64 %p7, %rd57, 0; ; CHECK-NEXT: and.pred %p8, %p7, %p6; -; CHECK-NEXT: setp.ne.b64 %p9, %rd6, 0; +; CHECK-NEXT: setp.ne.b64 %p9, %rd57, 0; ; CHECK-NEXT: or.pred %p10, %p8, %p9; ; CHECK-NEXT: or.pred %p11, %p3, %p10; -; CHECK-NEXT: xor.b64 %rd56, %rd5, 127; -; CHECK-NEXT: or.b64 %rd57, %rd56, %rd6; -; CHECK-NEXT: setp.eq.b64 %p12, %rd57, 0; -; CHECK-NEXT: selp.b64 %rd110, 0, %rd42, %p11; -; CHECK-NEXT: selp.b64 %rd109, 0, %rd41, %p11; +; CHECK-NEXT: xor.b64 %rd58, %rd56, 127; +; CHECK-NEXT: or.b64 %rd59, %rd58, %rd57; +; CHECK-NEXT: setp.eq.b64 %p12, %rd59, 0; +; CHECK-NEXT: selp.b64 %rd112, 0, %rd42, %p11; +; CHECK-NEXT: selp.b64 %rd111, 0, %rd41, %p11; ; CHECK-NEXT: or.pred %p13, %p11, %p12; ; CHECK-NEXT: @%p13 bra $L__BB1_5; ; CHECK-NEXT: // %bb.3: // %udiv-bb1 -; CHECK-NEXT: add.cc.s64 %rd103, %rd5, 1; -; CHECK-NEXT: addc.cc.s64 %rd104, %rd6, 0; -; CHECK-NEXT: or.b64 %rd60, %rd103, %rd104; -; CHECK-NEXT: setp.eq.b64 %p14, %rd60, 0; -; CHECK-NEXT: cvt.u32.u64 %r5, %rd5; +; CHECK-NEXT: add.cc.s64 %rd105, %rd56, 1; +; CHECK-NEXT: addc.cc.s64 %rd106, %rd57, 0; +; CHECK-NEXT: or.b64 %rd62, %rd105, %rd106; +; CHECK-NEXT: setp.eq.b64 %p14, %rd62, 0; +; CHECK-NEXT: cvt.u32.u64 %r5, %rd56; ; CHECK-NEXT: sub.s32 %r6, 127, %r5; -; CHECK-NEXT: shl.b64 %rd61, %rd42, %r6; +; CHECK-NEXT: shl.b64 %rd63, %rd42, %r6; ; CHECK-NEXT: sub.s32 %r7, 64, %r6; -; CHECK-NEXT: shr.u64 %rd62, %rd41, %r7; -; CHECK-NEXT: or.b64 %rd63, %rd61, %rd62; +; CHECK-NEXT: shr.u64 %rd64, %rd41, %r7; +; CHECK-NEXT: or.b64 %rd65, %rd63, %rd64; ; CHECK-NEXT: sub.s32 %r8, 63, %r5; -; CHECK-NEXT: shl.b64 %rd64, %rd41, %r8; +; CHECK-NEXT: shl.b64 %rd66, %rd41, %r8; ; CHECK-NEXT: setp.gt.s32 %p15, %r6, 63; -; CHECK-NEXT: selp.b64 %rd108, %rd64, %rd63, %p15; -; CHECK-NEXT: shl.b64 %rd107, %rd41, %r6; -; CHECK-NEXT: mov.b64 %rd98, %rd101; +; CHECK-NEXT: selp.b64 %rd110, %rd66, %rd65, %p15; +; CHECK-NEXT: shl.b64 %rd109, %rd41, %r6; +; CHECK-NEXT: mov.b64 %rd100, %rd103; ; CHECK-NEXT: @%p14 bra $L__BB1_4; ; CHECK-NEXT: // %bb.1: // %udiv-preheader -; CHECK-NEXT: cvt.u32.u64 %r9, %rd103; -; CHECK-NEXT: shr.u64 %rd67, %rd41, %r9; +; CHECK-NEXT: cvt.u32.u64 %r9, %rd105; +; CHECK-NEXT: shr.u64 %rd69, %rd41, %r9; ; CHECK-NEXT: sub.s32 %r10, 64, %r9; -; CHECK-NEXT: shl.b64 %rd68, %rd42, %r10; -; CHECK-NEXT: or.b64 %rd69, %rd67, %rd68; +; CHECK-NEXT: shl.b64 %rd70, %rd42, %r10; +; CHECK-NEXT: or.b64 %rd71, %rd69, %rd70; ; CHECK-NEXT: add.s32 %r11, %r9, -64; -; CHECK-NEXT: shr.u64 %rd70, %rd42, %r11; +; CHECK-NEXT: shr.u64 %rd72, %rd42, %r11; ; CHECK-NEXT: setp.gt.s32 %p16, %r9, 63; -; CHECK-NEXT: selp.b64 %rd105, %rd70, %rd69, %p16; -; CHECK-NEXT: shr.u64 %rd106, %rd42, %r9; +; CHECK-NEXT: selp.b64 %rd107, %rd72, %rd71, %p16; +; CHECK-NEXT: shr.u64 %rd108, %rd42, %r9; ; CHECK-NEXT: add.cc.s64 %rd33, %rd3, -1; ; CHECK-NEXT: addc.cc.s64 %rd34, %rd4, -1; -; CHECK-NEXT: mov.b64 %rd98, 0; -; CHECK-NEXT: mov.b64 %rd101, %rd98; +; CHECK-NEXT: mov.b64 %rd100, 0; +; CHECK-NEXT: mov.b64 %rd103, %rd100; ; CHECK-NEXT: $L__BB1_2: // %udiv-do-while ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: shr.u64 %rd71, %rd105, 63; -; CHECK-NEXT: shl.b64 %rd72, %rd106, 1; -; CHECK-NEXT: or.b64 %rd73, %rd72, %rd71; -; CHECK-NEXT: shl.b64 %rd74, %rd105, 1; -; CHECK-NEXT: shr.u64 %rd75, %rd108, 63; -; CHECK-NEXT: or.b64 %rd76, %rd74, %rd75; -; CHECK-NEXT: shr.u64 %rd77, %rd107, 63; -; CHECK-NEXT: shl.b64 %rd78, %rd108, 1; -; CHECK-NEXT: or.b64 %rd79, %rd78, %rd77; -; CHECK-NEXT: shl.b64 %rd80, %rd107, 1; -; CHECK-NEXT: or.b64 %rd107, %rd101, %rd80; -; CHECK-NEXT: or.b64 %rd108, %rd98, %rd79; -; CHECK-NEXT: sub.cc.s64 %rd81, %rd33, %rd76; -; CHECK-NEXT: subc.cc.s64 %rd82, %rd34, %rd73; -; CHECK-NEXT: shr.s64 %rd83, %rd82, 63; -; CHECK-NEXT: and.b64 %rd101, %rd83, 1; -; CHECK-NEXT: and.b64 %rd84, %rd83, %rd3; -; CHECK-NEXT: and.b64 %rd85, %rd83, %rd4; -; CHECK-NEXT: sub.cc.s64 %rd105, %rd76, %rd84; -; CHECK-NEXT: subc.cc.s64 %rd106, %rd73, %rd85; -; CHECK-NEXT: add.cc.s64 %rd103, %rd103, -1; -; CHECK-NEXT: addc.cc.s64 %rd104, %rd104, -1; -; CHECK-NEXT: or.b64 %rd86, %rd103, %rd104; -; CHECK-NEXT: setp.eq.b64 %p17, %rd86, 0; +; CHECK-NEXT: shr.u64 %rd73, %rd107, 63; +; CHECK-NEXT: shl.b64 %rd74, %rd108, 1; +; CHECK-NEXT: or.b64 %rd75, %rd74, %rd73; +; CHECK-NEXT: shl.b64 %rd76, %rd107, 1; +; CHECK-NEXT: shr.u64 %rd77, %rd110, 63; +; CHECK-NEXT: or.b64 %rd78, %rd76, %rd77; +; CHECK-NEXT: shr.u64 %rd79, %rd109, 63; +; CHECK-NEXT: shl.b64 %rd80, %rd110, 1; +; CHECK-NEXT: or.b64 %rd81, %rd80, %rd79; +; CHECK-NEXT: shl.b64 %rd82, %rd109, 1; +; CHECK-NEXT: or.b64 %rd109, %rd103, %rd82; +; CHECK-NEXT: or.b64 %rd110, %rd100, %rd81; +; CHECK-NEXT: sub.cc.s64 %rd83, %rd33, %rd78; +; CHECK-NEXT: subc.cc.s64 %rd84, %rd34, %rd75; +; CHECK-NEXT: shr.s64 %rd85, %rd84, 63; +; CHECK-NEXT: and.b64 %rd103, %rd85, 1; +; CHECK-NEXT: and.b64 %rd86, %rd85, %rd3; +; CHECK-NEXT: and.b64 %rd87, %rd85, %rd4; +; CHECK-NEXT: sub.cc.s64 %rd107, %rd78, %rd86; +; CHECK-NEXT: subc.cc.s64 %rd108, %rd75, %rd87; +; CHECK-NEXT: add.cc.s64 %rd105, %rd105, -1; +; CHECK-NEXT: addc.cc.s64 %rd106, %rd106, -1; +; CHECK-NEXT: or.b64 %rd88, %rd105, %rd106; +; CHECK-NEXT: setp.eq.b64 %p17, %rd88, 0; ; CHECK-NEXT: @%p17 bra $L__BB1_4; ; CHECK-NEXT: bra.uni $L__BB1_2; ; CHECK-NEXT: $L__BB1_4: // %udiv-loop-exit -; CHECK-NEXT: shr.u64 %rd87, %rd107, 63; -; CHECK-NEXT: shl.b64 %rd88, %rd108, 1; -; CHECK-NEXT: or.b64 %rd89, %rd88, %rd87; -; CHECK-NEXT: shl.b64 %rd90, %rd107, 1; -; CHECK-NEXT: or.b64 %rd109, %rd101, %rd90; -; CHECK-NEXT: or.b64 %rd110, %rd98, %rd89; +; CHECK-NEXT: shr.u64 %rd89, %rd109, 63; +; CHECK-NEXT: shl.b64 %rd90, %rd110, 1; +; CHECK-NEXT: or.b64 %rd91, %rd90, %rd89; +; CHECK-NEXT: shl.b64 %rd92, %rd109, 1; +; CHECK-NEXT: or.b64 %rd111, %rd103, %rd92; +; CHECK-NEXT: or.b64 %rd112, %rd100, %rd91; ; CHECK-NEXT: $L__BB1_5: // %udiv-end -; CHECK-NEXT: mul.hi.u64 %rd91, %rd3, %rd109; -; CHECK-NEXT: mad.lo.s64 %rd92, %rd3, %rd110, %rd91; -; CHECK-NEXT: mad.lo.s64 %rd93, %rd4, %rd109, %rd92; -; CHECK-NEXT: mul.lo.s64 %rd94, %rd3, %rd109; -; CHECK-NEXT: sub.cc.s64 %rd95, %rd41, %rd94; -; CHECK-NEXT: subc.cc.s64 %rd96, %rd42, %rd93; -; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd95, %rd96}; +; CHECK-NEXT: mul.hi.u64 %rd93, %rd3, %rd111; +; CHECK-NEXT: mad.lo.s64 %rd94, %rd3, %rd112, %rd93; +; CHECK-NEXT: mad.lo.s64 %rd95, %rd4, %rd111, %rd94; +; CHECK-NEXT: mul.lo.s64 %rd96, %rd3, %rd111; +; CHECK-NEXT: sub.cc.s64 %rd97, %rd41, %rd96; +; CHECK-NEXT: subc.cc.s64 %rd98, %rd42, %rd95; +; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd97, %rd98}; ; CHECK-NEXT: ret; %div = urem i128 %lhs, %rhs ret i128 %div @@ -307,9 +306,9 @@ define i128 @urem_i128_pow2k(i128 %lhs) { define i128 @sdiv_i128(i128 %lhs, i128 %rhs) { ; CHECK-LABEL: sdiv_i128( ; CHECK: { -; CHECK-NEXT: .reg .pred %p<22>; +; CHECK-NEXT: .reg .pred %p<20>; ; CHECK-NEXT: .reg .b32 %r<12>; -; CHECK-NEXT: .reg .b64 %rd<121>; +; CHECK-NEXT: .reg .b64 %rd<122>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: // %_udiv-special-cases ; CHECK-NEXT: ld.param.v2.b64 {%rd45, %rd46}, [sdiv_i128_param_0]; @@ -345,97 +344,96 @@ define i128 @sdiv_i128(i128 %lhs, i128 %rhs) { ; CHECK-NEXT: cvt.u64.u32 %rd63, %r4; ; CHECK-NEXT: add.s64 %rd64, %rd63, 64; ; CHECK-NEXT: selp.b64 %rd65, %rd62, %rd64, %p7; -; CHECK-NEXT: mov.b64 %rd111, 0; +; CHECK-NEXT: mov.b64 %rd112, 0; ; CHECK-NEXT: sub.cc.s64 %rd67, %rd61, %rd65; -; CHECK-NEXT: subc.cc.s64 %rd8, %rd111, 0; -; CHECK-NEXT: setp.ne.b64 %p8, %rd8, 0; -; CHECK-NEXT: and.pred %p10, %p8, %p8; -; CHECK-NEXT: setp.eq.b64 %p11, %rd8, 0; -; CHECK-NEXT: setp.gt.u64 %p12, %rd67, 127; -; CHECK-NEXT: and.pred %p13, %p11, %p12; -; CHECK-NEXT: or.pred %p14, %p13, %p10; -; CHECK-NEXT: or.pred %p15, %p5, %p14; -; CHECK-NEXT: xor.b64 %rd68, %rd67, 127; -; CHECK-NEXT: or.b64 %rd69, %rd68, %rd8; -; CHECK-NEXT: setp.eq.b64 %p16, %rd69, 0; -; CHECK-NEXT: selp.b64 %rd120, 0, %rd2, %p15; -; CHECK-NEXT: selp.b64 %rd119, 0, %rd1, %p15; -; CHECK-NEXT: or.pred %p17, %p15, %p16; -; CHECK-NEXT: @%p17 bra $L__BB4_5; +; CHECK-NEXT: subc.cc.s64 %rd68, %rd112, 0; +; CHECK-NEXT: setp.gt.u64 %p8, %rd67, 127; +; CHECK-NEXT: setp.eq.b64 %p9, %rd68, 0; +; CHECK-NEXT: and.pred %p10, %p9, %p8; +; CHECK-NEXT: setp.ne.b64 %p11, %rd68, 0; +; CHECK-NEXT: or.pred %p12, %p10, %p11; +; CHECK-NEXT: or.pred %p13, %p5, %p12; +; CHECK-NEXT: xor.b64 %rd69, %rd67, 127; +; CHECK-NEXT: or.b64 %rd70, %rd69, %rd68; +; CHECK-NEXT: setp.eq.b64 %p14, %rd70, 0; +; CHECK-NEXT: selp.b64 %rd121, 0, %rd2, %p13; +; CHECK-NEXT: selp.b64 %rd120, 0, %rd1, %p13; +; CHECK-NEXT: or.pred %p15, %p13, %p14; +; CHECK-NEXT: @%p15 bra $L__BB4_5; ; CHECK-NEXT: // %bb.3: // %udiv-bb1 -; CHECK-NEXT: add.cc.s64 %rd113, %rd67, 1; -; CHECK-NEXT: addc.cc.s64 %rd114, %rd8, 0; -; CHECK-NEXT: or.b64 %rd72, %rd113, %rd114; -; CHECK-NEXT: setp.eq.b64 %p18, %rd72, 0; +; CHECK-NEXT: add.cc.s64 %rd114, %rd67, 1; +; CHECK-NEXT: addc.cc.s64 %rd115, %rd68, 0; +; CHECK-NEXT: or.b64 %rd73, %rd114, %rd115; +; CHECK-NEXT: setp.eq.b64 %p16, %rd73, 0; ; CHECK-NEXT: cvt.u32.u64 %r5, %rd67; ; CHECK-NEXT: sub.s32 %r6, 127, %r5; -; CHECK-NEXT: shl.b64 %rd73, %rd2, %r6; +; CHECK-NEXT: shl.b64 %rd74, %rd2, %r6; ; CHECK-NEXT: sub.s32 %r7, 64, %r6; -; CHECK-NEXT: shr.u64 %rd74, %rd1, %r7; -; CHECK-NEXT: or.b64 %rd75, %rd73, %rd74; +; CHECK-NEXT: shr.u64 %rd75, %rd1, %r7; +; CHECK-NEXT: or.b64 %rd76, %rd74, %rd75; ; CHECK-NEXT: sub.s32 %r8, 63, %r5; -; CHECK-NEXT: shl.b64 %rd76, %rd1, %r8; -; CHECK-NEXT: setp.gt.s32 %p19, %r6, 63; -; CHECK-NEXT: selp.b64 %rd118, %rd76, %rd75, %p19; -; CHECK-NEXT: shl.b64 %rd117, %rd1, %r6; -; CHECK-NEXT: mov.b64 %rd108, %rd111; -; CHECK-NEXT: @%p18 bra $L__BB4_4; +; CHECK-NEXT: shl.b64 %rd77, %rd1, %r8; +; CHECK-NEXT: setp.gt.s32 %p17, %r6, 63; +; CHECK-NEXT: selp.b64 %rd119, %rd77, %rd76, %p17; +; CHECK-NEXT: shl.b64 %rd118, %rd1, %r6; +; CHECK-NEXT: mov.b64 %rd109, %rd112; +; CHECK-NEXT: @%p16 bra $L__BB4_4; ; CHECK-NEXT: // %bb.1: // %udiv-preheader -; CHECK-NEXT: cvt.u32.u64 %r9, %rd113; -; CHECK-NEXT: shr.u64 %rd79, %rd1, %r9; +; CHECK-NEXT: cvt.u32.u64 %r9, %rd114; +; CHECK-NEXT: shr.u64 %rd80, %rd1, %r9; ; CHECK-NEXT: sub.s32 %r10, 64, %r9; -; CHECK-NEXT: shl.b64 %rd80, %rd2, %r10; -; CHECK-NEXT: or.b64 %rd81, %rd79, %rd80; +; CHECK-NEXT: shl.b64 %rd81, %rd2, %r10; +; CHECK-NEXT: or.b64 %rd82, %rd80, %rd81; ; CHECK-NEXT: add.s32 %r11, %r9, -64; -; CHECK-NEXT: shr.u64 %rd82, %rd2, %r11; -; CHECK-NEXT: setp.gt.s32 %p20, %r9, 63; -; CHECK-NEXT: selp.b64 %rd115, %rd82, %rd81, %p20; -; CHECK-NEXT: shr.u64 %rd116, %rd2, %r9; +; CHECK-NEXT: shr.u64 %rd83, %rd2, %r11; +; CHECK-NEXT: setp.gt.s32 %p18, %r9, 63; +; CHECK-NEXT: selp.b64 %rd116, %rd83, %rd82, %p18; +; CHECK-NEXT: shr.u64 %rd117, %rd2, %r9; ; CHECK-NEXT: add.cc.s64 %rd35, %rd3, -1; ; CHECK-NEXT: addc.cc.s64 %rd36, %rd4, -1; -; CHECK-NEXT: mov.b64 %rd108, 0; -; CHECK-NEXT: mov.b64 %rd111, %rd108; +; CHECK-NEXT: mov.b64 %rd109, 0; +; CHECK-NEXT: mov.b64 %rd112, %rd109; ; CHECK-NEXT: $L__BB4_2: // %udiv-do-while ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: shr.u64 %rd83, %rd115, 63; -; CHECK-NEXT: shl.b64 %rd84, %rd116, 1; -; CHECK-NEXT: or.b64 %rd85, %rd84, %rd83; -; CHECK-NEXT: shl.b64 %rd86, %rd115, 1; -; CHECK-NEXT: shr.u64 %rd87, %rd118, 63; -; CHECK-NEXT: or.b64 %rd88, %rd86, %rd87; -; CHECK-NEXT: shr.u64 %rd89, %rd117, 63; -; CHECK-NEXT: shl.b64 %rd90, %rd118, 1; -; CHECK-NEXT: or.b64 %rd91, %rd90, %rd89; -; CHECK-NEXT: shl.b64 %rd92, %rd117, 1; -; CHECK-NEXT: or.b64 %rd117, %rd111, %rd92; -; CHECK-NEXT: or.b64 %rd118, %rd108, %rd91; -; CHECK-NEXT: sub.cc.s64 %rd93, %rd35, %rd88; -; CHECK-NEXT: subc.cc.s64 %rd94, %rd36, %rd85; -; CHECK-NEXT: shr.s64 %rd95, %rd94, 63; -; CHECK-NEXT: and.b64 %rd111, %rd95, 1; -; CHECK-NEXT: and.b64 %rd96, %rd95, %rd3; -; CHECK-NEXT: and.b64 %rd97, %rd95, %rd4; -; CHECK-NEXT: sub.cc.s64 %rd115, %rd88, %rd96; -; CHECK-NEXT: subc.cc.s64 %rd116, %rd85, %rd97; -; CHECK-NEXT: add.cc.s64 %rd113, %rd113, -1; -; CHECK-NEXT: addc.cc.s64 %rd114, %rd114, -1; -; CHECK-NEXT: or.b64 %rd98, %rd113, %rd114; -; CHECK-NEXT: setp.eq.b64 %p21, %rd98, 0; -; CHECK-NEXT: @%p21 bra $L__BB4_4; +; CHECK-NEXT: shr.u64 %rd84, %rd116, 63; +; CHECK-NEXT: shl.b64 %rd85, %rd117, 1; +; CHECK-NEXT: or.b64 %rd86, %rd85, %rd84; +; CHECK-NEXT: shl.b64 %rd87, %rd116, 1; +; CHECK-NEXT: shr.u64 %rd88, %rd119, 63; +; CHECK-NEXT: or.b64 %rd89, %rd87, %rd88; +; CHECK-NEXT: shr.u64 %rd90, %rd118, 63; +; CHECK-NEXT: shl.b64 %rd91, %rd119, 1; +; CHECK-NEXT: or.b64 %rd92, %rd91, %rd90; +; CHECK-NEXT: shl.b64 %rd93, %rd118, 1; +; CHECK-NEXT: or.b64 %rd118, %rd112, %rd93; +; CHECK-NEXT: or.b64 %rd119, %rd109, %rd92; +; CHECK-NEXT: sub.cc.s64 %rd94, %rd35, %rd89; +; CHECK-NEXT: subc.cc.s64 %rd95, %rd36, %rd86; +; CHECK-NEXT: shr.s64 %rd96, %rd95, 63; +; CHECK-NEXT: and.b64 %rd112, %rd96, 1; +; CHECK-NEXT: and.b64 %rd97, %rd96, %rd3; +; CHECK-NEXT: and.b64 %rd98, %rd96, %rd4; +; CHECK-NEXT: sub.cc.s64 %rd116, %rd89, %rd97; +; CHECK-NEXT: subc.cc.s64 %rd117, %rd86, %rd98; +; CHECK-NEXT: add.cc.s64 %rd114, %rd114, -1; +; CHECK-NEXT: addc.cc.s64 %rd115, %rd115, -1; +; CHECK-NEXT: or.b64 %rd99, %rd114, %rd115; +; CHECK-NEXT: setp.eq.b64 %p19, %rd99, 0; +; CHECK-NEXT: @%p19 bra $L__BB4_4; ; CHECK-NEXT: bra.uni $L__BB4_2; ; CHECK-NEXT: $L__BB4_4: // %udiv-loop-exit -; CHECK-NEXT: shr.u64 %rd99, %rd117, 63; -; CHECK-NEXT: shl.b64 %rd100, %rd118, 1; -; CHECK-NEXT: or.b64 %rd101, %rd100, %rd99; -; CHECK-NEXT: shl.b64 %rd102, %rd117, 1; -; CHECK-NEXT: or.b64 %rd119, %rd111, %rd102; -; CHECK-NEXT: or.b64 %rd120, %rd108, %rd101; +; CHECK-NEXT: shr.u64 %rd100, %rd118, 63; +; CHECK-NEXT: shl.b64 %rd101, %rd119, 1; +; CHECK-NEXT: or.b64 %rd102, %rd101, %rd100; +; CHECK-NEXT: shl.b64 %rd103, %rd118, 1; +; CHECK-NEXT: or.b64 %rd120, %rd112, %rd103; +; CHECK-NEXT: or.b64 %rd121, %rd109, %rd102; ; CHECK-NEXT: $L__BB4_5: // %udiv-end -; CHECK-NEXT: xor.b64 %rd103, %rd119, %rd5; ; CHECK-NEXT: xor.b64 %rd104, %rd120, %rd5; -; CHECK-NEXT: sub.cc.s64 %rd105, %rd103, %rd5; -; CHECK-NEXT: subc.cc.s64 %rd106, %rd104, %rd5; -; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd105, %rd106}; +; CHECK-NEXT: xor.b64 %rd105, %rd121, %rd5; +; CHECK-NEXT: sub.cc.s64 %rd106, %rd104, %rd5; +; CHECK-NEXT: subc.cc.s64 %rd107, %rd105, %rd5; +; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd106, %rd107}; ; CHECK-NEXT: ret; %div = sdiv i128 %lhs, %rhs ret i128 %div @@ -446,7 +444,7 @@ define i128 @udiv_i128(i128 %lhs, i128 %rhs) { ; CHECK: { ; CHECK-NEXT: .reg .pred %p<18>; ; CHECK-NEXT: .reg .b32 %r<12>; -; CHECK-NEXT: .reg .b64 %rd<105>; +; CHECK-NEXT: .reg .b64 %rd<107>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: // %_udiv-special-cases ; CHECK-NEXT: ld.param.v2.b64 {%rd41, %rd42}, [udiv_i128_param_0]; @@ -470,92 +468,92 @@ define i128 @udiv_i128(i128 %lhs, i128 %rhs) { ; CHECK-NEXT: cvt.u64.u32 %rd52, %r4; ; CHECK-NEXT: add.s64 %rd53, %rd52, 64; ; CHECK-NEXT: selp.b64 %rd54, %rd51, %rd53, %p5; -; CHECK-NEXT: mov.b64 %rd95, 0; -; CHECK-NEXT: sub.cc.s64 %rd5, %rd50, %rd54; -; CHECK-NEXT: subc.cc.s64 %rd6, %rd95, 0; -; CHECK-NEXT: setp.gt.u64 %p6, %rd5, 127; -; CHECK-NEXT: setp.eq.b64 %p7, %rd6, 0; +; CHECK-NEXT: mov.b64 %rd97, 0; +; CHECK-NEXT: sub.cc.s64 %rd56, %rd50, %rd54; +; CHECK-NEXT: subc.cc.s64 %rd57, %rd97, 0; +; CHECK-NEXT: setp.gt.u64 %p6, %rd56, 127; +; CHECK-NEXT: setp.eq.b64 %p7, %rd57, 0; ; CHECK-NEXT: and.pred %p8, %p7, %p6; -; CHECK-NEXT: setp.ne.b64 %p9, %rd6, 0; +; CHECK-NEXT: setp.ne.b64 %p9, %rd57, 0; ; CHECK-NEXT: or.pred %p10, %p8, %p9; ; CHECK-NEXT: or.pred %p11, %p3, %p10; -; CHECK-NEXT: xor.b64 %rd56, %rd5, 127; -; CHECK-NEXT: or.b64 %rd57, %rd56, %rd6; -; CHECK-NEXT: setp.eq.b64 %p12, %rd57, 0; -; CHECK-NEXT: selp.b64 %rd104, 0, %rd42, %p11; -; CHECK-NEXT: selp.b64 %rd103, 0, %rd41, %p11; +; CHECK-NEXT: xor.b64 %rd58, %rd56, 127; +; CHECK-NEXT: or.b64 %rd59, %rd58, %rd57; +; CHECK-NEXT: setp.eq.b64 %p12, %rd59, 0; +; CHECK-NEXT: selp.b64 %rd106, 0, %rd42, %p11; +; CHECK-NEXT: selp.b64 %rd105, 0, %rd41, %p11; ; CHECK-NEXT: or.pred %p13, %p11, %p12; ; CHECK-NEXT: @%p13 bra $L__BB5_5; ; CHECK-NEXT: // %bb.3: // %udiv-bb1 -; CHECK-NEXT: add.cc.s64 %rd97, %rd5, 1; -; CHECK-NEXT: addc.cc.s64 %rd98, %rd6, 0; -; CHECK-NEXT: or.b64 %rd60, %rd97, %rd98; -; CHECK-NEXT: setp.eq.b64 %p14, %rd60, 0; -; CHECK-NEXT: cvt.u32.u64 %r5, %rd5; +; CHECK-NEXT: add.cc.s64 %rd99, %rd56, 1; +; CHECK-NEXT: addc.cc.s64 %rd100, %rd57, 0; +; CHECK-NEXT: or.b64 %rd62, %rd99, %rd100; +; CHECK-NEXT: setp.eq.b64 %p14, %rd62, 0; +; CHECK-NEXT: cvt.u32.u64 %r5, %rd56; ; CHECK-NEXT: sub.s32 %r6, 127, %r5; -; CHECK-NEXT: shl.b64 %rd61, %rd42, %r6; +; CHECK-NEXT: shl.b64 %rd63, %rd42, %r6; ; CHECK-NEXT: sub.s32 %r7, 64, %r6; -; CHECK-NEXT: shr.u64 %rd62, %rd41, %r7; -; CHECK-NEXT: or.b64 %rd63, %rd61, %rd62; +; CHECK-NEXT: shr.u64 %rd64, %rd41, %r7; +; CHECK-NEXT: or.b64 %rd65, %rd63, %rd64; ; CHECK-NEXT: sub.s32 %r8, 63, %r5; -; CHECK-NEXT: shl.b64 %rd64, %rd41, %r8; +; CHECK-NEXT: shl.b64 %rd66, %rd41, %r8; ; CHECK-NEXT: setp.gt.s32 %p15, %r6, 63; -; CHECK-NEXT: selp.b64 %rd102, %rd64, %rd63, %p15; -; CHECK-NEXT: shl.b64 %rd101, %rd41, %r6; -; CHECK-NEXT: mov.b64 %rd92, %rd95; +; CHECK-NEXT: selp.b64 %rd104, %rd66, %rd65, %p15; +; CHECK-NEXT: shl.b64 %rd103, %rd41, %r6; +; CHECK-NEXT: mov.b64 %rd94, %rd97; ; CHECK-NEXT: @%p14 bra $L__BB5_4; ; CHECK-NEXT: // %bb.1: // %udiv-preheader -; CHECK-NEXT: cvt.u32.u64 %r9, %rd97; -; CHECK-NEXT: shr.u64 %rd67, %rd41, %r9; +; CHECK-NEXT: cvt.u32.u64 %r9, %rd99; +; CHECK-NEXT: shr.u64 %rd69, %rd41, %r9; ; CHECK-NEXT: sub.s32 %r10, 64, %r9; -; CHECK-NEXT: shl.b64 %rd68, %rd42, %r10; -; CHECK-NEXT: or.b64 %rd69, %rd67, %rd68; +; CHECK-NEXT: shl.b64 %rd70, %rd42, %r10; +; CHECK-NEXT: or.b64 %rd71, %rd69, %rd70; ; CHECK-NEXT: add.s32 %r11, %r9, -64; -; CHECK-NEXT: shr.u64 %rd70, %rd42, %r11; +; CHECK-NEXT: shr.u64 %rd72, %rd42, %r11; ; CHECK-NEXT: setp.gt.s32 %p16, %r9, 63; -; CHECK-NEXT: selp.b64 %rd99, %rd70, %rd69, %p16; -; CHECK-NEXT: shr.u64 %rd100, %rd42, %r9; +; CHECK-NEXT: selp.b64 %rd101, %rd72, %rd71, %p16; +; CHECK-NEXT: shr.u64 %rd102, %rd42, %r9; ; CHECK-NEXT: add.cc.s64 %rd33, %rd43, -1; ; CHECK-NEXT: addc.cc.s64 %rd34, %rd44, -1; -; CHECK-NEXT: mov.b64 %rd92, 0; -; CHECK-NEXT: mov.b64 %rd95, %rd92; +; CHECK-NEXT: mov.b64 %rd94, 0; +; CHECK-NEXT: mov.b64 %rd97, %rd94; ; CHECK-NEXT: $L__BB5_2: // %udiv-do-while ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: shr.u64 %rd71, %rd99, 63; -; CHECK-NEXT: shl.b64 %rd72, %rd100, 1; -; CHECK-NEXT: or.b64 %rd73, %rd72, %rd71; -; CHECK-NEXT: shl.b64 %rd74, %rd99, 1; -; CHECK-NEXT: shr.u64 %rd75, %rd102, 63; -; CHECK-NEXT: or.b64 %rd76, %rd74, %rd75; -; CHECK-NEXT: shr.u64 %rd77, %rd101, 63; -; CHECK-NEXT: shl.b64 %rd78, %rd102, 1; -; CHECK-NEXT: or.b64 %rd79, %rd78, %rd77; -; CHECK-NEXT: shl.b64 %rd80, %rd101, 1; -; CHECK-NEXT: or.b64 %rd101, %rd95, %rd80; -; CHECK-NEXT: or.b64 %rd102, %rd92, %rd79; -; CHECK-NEXT: sub.cc.s64 %rd81, %rd33, %rd76; -; CHECK-NEXT: subc.cc.s64 %rd82, %rd34, %rd73; -; CHECK-NEXT: shr.s64 %rd83, %rd82, 63; -; CHECK-NEXT: and.b64 %rd95, %rd83, 1; -; CHECK-NEXT: and.b64 %rd84, %rd83, %rd43; -; CHECK-NEXT: and.b64 %rd85, %rd83, %rd44; -; CHECK-NEXT: sub.cc.s64 %rd99, %rd76, %rd84; -; CHECK-NEXT: subc.cc.s64 %rd100, %rd73, %rd85; -; CHECK-NEXT: add.cc.s64 %rd97, %rd97, -1; -; CHECK-NEXT: addc.cc.s64 %rd98, %rd98, -1; -; CHECK-NEXT: or.b64 %rd86, %rd97, %rd98; -; CHECK-NEXT: setp.eq.b64 %p17, %rd86, 0; +; CHECK-NEXT: shr.u64 %rd73, %rd101, 63; +; CHECK-NEXT: shl.b64 %rd74, %rd102, 1; +; CHECK-NEXT: or.b64 %rd75, %rd74, %rd73; +; CHECK-NEXT: shl.b64 %rd76, %rd101, 1; +; CHECK-NEXT: shr.u64 %rd77, %rd104, 63; +; CHECK-NEXT: or.b64 %rd78, %rd76, %rd77; +; CHECK-NEXT: shr.u64 %rd79, %rd103, 63; +; CHECK-NEXT: shl.b64 %rd80, %rd104, 1; +; CHECK-NEXT: or.b64 %rd81, %rd80, %rd79; +; CHECK-NEXT: shl.b64 %rd82, %rd103, 1; +; CHECK-NEXT: or.b64 %rd103, %rd97, %rd82; +; CHECK-NEXT: or.b64 %rd104, %rd94, %rd81; +; CHECK-NEXT: sub.cc.s64 %rd83, %rd33, %rd78; +; CHECK-NEXT: subc.cc.s64 %rd84, %rd34, %rd75; +; CHECK-NEXT: shr.s64 %rd85, %rd84, 63; +; CHECK-NEXT: and.b64 %rd97, %rd85, 1; +; CHECK-NEXT: and.b64 %rd86, %rd85, %rd43; +; CHECK-NEXT: and.b64 %rd87, %rd85, %rd44; +; CHECK-NEXT: sub.cc.s64 %rd101, %rd78, %rd86; +; CHECK-NEXT: subc.cc.s64 %rd102, %rd75, %rd87; +; CHECK-NEXT: add.cc.s64 %rd99, %rd99, -1; +; CHECK-NEXT: addc.cc.s64 %rd100, %rd100, -1; +; CHECK-NEXT: or.b64 %rd88, %rd99, %rd100; +; CHECK-NEXT: setp.eq.b64 %p17, %rd88, 0; ; CHECK-NEXT: @%p17 bra $L__BB5_4; ; CHECK-NEXT: bra.uni $L__BB5_2; ; CHECK-NEXT: $L__BB5_4: // %udiv-loop-exit -; CHECK-NEXT: shr.u64 %rd87, %rd101, 63; -; CHECK-NEXT: shl.b64 %rd88, %rd102, 1; -; CHECK-NEXT: or.b64 %rd89, %rd88, %rd87; -; CHECK-NEXT: shl.b64 %rd90, %rd101, 1; -; CHECK-NEXT: or.b64 %rd103, %rd95, %rd90; -; CHECK-NEXT: or.b64 %rd104, %rd92, %rd89; +; CHECK-NEXT: shr.u64 %rd89, %rd103, 63; +; CHECK-NEXT: shl.b64 %rd90, %rd104, 1; +; CHECK-NEXT: or.b64 %rd91, %rd90, %rd89; +; CHECK-NEXT: shl.b64 %rd92, %rd103, 1; +; CHECK-NEXT: or.b64 %rd105, %rd97, %rd92; +; CHECK-NEXT: or.b64 %rd106, %rd94, %rd91; ; CHECK-NEXT: $L__BB5_5: // %udiv-end -; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd103, %rd104}; +; CHECK-NEXT: st.param.v2.b64 [func_retval0], {%rd105, %rd106}; ; CHECK-NEXT: ret; %div = udiv i128 %lhs, %rhs ret i128 %div diff --git a/llvm/test/CodeGen/NVPTX/i16x2-instructions.ll b/llvm/test/CodeGen/NVPTX/i16x2-instructions.ll index 1a61498b10142..2b7a06c33d948 100644 --- a/llvm/test/CodeGen/NVPTX/i16x2-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/i16x2-instructions.ll @@ -32,31 +32,57 @@ define <2 x i16> @test_ret_const() #0 { } define i16 @test_extract_0(<2 x i16> %a) #0 { -; COMMON-LABEL: test_extract_0( -; COMMON: { -; COMMON-NEXT: .reg .b16 %rs<3>; -; COMMON-NEXT: .reg .b32 %r<3>; -; COMMON-EMPTY: -; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_0_param_0]; -; COMMON-NEXT: cvt.u32.u16 %r2, %rs1; -; COMMON-NEXT: st.param.b32 [func_retval0], %r2; -; COMMON-NEXT: ret; +; I16x2-LABEL: test_extract_0( +; I16x2: { +; I16x2-NEXT: .reg .b16 %rs<2>; +; I16x2-NEXT: .reg .b32 %r<3>; +; I16x2-EMPTY: +; I16x2-NEXT: // %bb.0: +; I16x2-NEXT: ld.param.b32 %r1, [test_extract_0_param_0]; +; I16x2-NEXT: mov.b32 {%rs1, _}, %r1; +; I16x2-NEXT: cvt.u32.u16 %r2, %rs1; +; I16x2-NEXT: st.param.b32 [func_retval0], %r2; +; I16x2-NEXT: ret; +; +; NO-I16x2-LABEL: test_extract_0( +; NO-I16x2: { +; NO-I16x2-NEXT: .reg .b16 %rs<2>; +; NO-I16x2-NEXT: .reg .b32 %r<3>; +; NO-I16x2-EMPTY: +; NO-I16x2-NEXT: // %bb.0: +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_extract_0_param_0]; +; NO-I16x2-NEXT: { .reg .b16 tmp; mov.b32 {%rs1, tmp}, %r1; } +; NO-I16x2-NEXT: cvt.u32.u16 %r2, %rs1; +; NO-I16x2-NEXT: st.param.b32 [func_retval0], %r2; +; NO-I16x2-NEXT: ret; %e = extractelement <2 x i16> %a, i32 0 ret i16 %e } define i16 @test_extract_1(<2 x i16> %a) #0 { -; COMMON-LABEL: test_extract_1( -; COMMON: { -; COMMON-NEXT: .reg .b16 %rs<3>; -; COMMON-NEXT: .reg .b32 %r<3>; -; COMMON-EMPTY: -; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_1_param_0]; -; COMMON-NEXT: cvt.u32.u16 %r2, %rs2; -; COMMON-NEXT: st.param.b32 [func_retval0], %r2; -; COMMON-NEXT: ret; +; I16x2-LABEL: test_extract_1( +; I16x2: { +; I16x2-NEXT: .reg .b16 %rs<2>; +; I16x2-NEXT: .reg .b32 %r<3>; +; I16x2-EMPTY: +; I16x2-NEXT: // %bb.0: +; I16x2-NEXT: ld.param.b32 %r1, [test_extract_1_param_0]; +; I16x2-NEXT: mov.b32 {_, %rs1}, %r1; +; I16x2-NEXT: cvt.u32.u16 %r2, %rs1; +; I16x2-NEXT: st.param.b32 [func_retval0], %r2; +; I16x2-NEXT: ret; +; +; NO-I16x2-LABEL: test_extract_1( +; NO-I16x2: { +; NO-I16x2-NEXT: .reg .b16 %rs<2>; +; NO-I16x2-NEXT: .reg .b32 %r<3>; +; NO-I16x2-EMPTY: +; NO-I16x2-NEXT: // %bb.0: +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_extract_1_param_0]; +; NO-I16x2-NEXT: { .reg .b16 tmp; mov.b32 {tmp, %rs1}, %r1; } +; NO-I16x2-NEXT: cvt.u32.u16 %r2, %rs1; +; NO-I16x2-NEXT: st.param.b32 [func_retval0], %r2; +; NO-I16x2-NEXT: ret; %e = extractelement <2 x i16> %a, i32 1 ret i16 %e } @@ -71,8 +97,9 @@ define i16 @test_extract_i(<2 x i16> %a, i64 %idx) #0 { ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: ; COMMON-NEXT: ld.param.b64 %rd1, [test_extract_i_param_1]; -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_extract_i_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_extract_i_param_0]; ; COMMON-NEXT: setp.eq.b64 %p1, %rd1, 0; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: selp.b16 %rs3, %rs1, %rs2, %p1; ; COMMON-NEXT: cvt.u32.u16 %r2, %rs3; ; COMMON-NEXT: st.param.b32 [func_retval0], %r2; @@ -99,10 +126,12 @@ define <2 x i16> @test_add(<2 x i16> %a, <2 x i16> %b) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<3>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_add_param_0]; -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_add_param_1]; -; NO-I16x2-NEXT: add.s16 %rs5, %rs2, %rs4; -; NO-I16x2-NEXT: add.s16 %rs6, %rs1, %rs3; +; NO-I16x2-NEXT: ld.param.b32 %r2, [test_add_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_add_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; NO-I16x2-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; NO-I16x2-NEXT: add.s16 %rs5, %rs4, %rs2; +; NO-I16x2-NEXT: add.s16 %rs6, %rs3, %rs1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; NO-I16x2-NEXT: ret; %r = add <2 x i16> %a, %b @@ -128,7 +157,8 @@ define <2 x i16> @test_add_imm_0(<2 x i16> %a) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<2>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_add_imm_0_param_0]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_add_imm_0_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; NO-I16x2-NEXT: add.s16 %rs3, %rs2, 2; ; NO-I16x2-NEXT: add.s16 %rs4, %rs1, 1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -155,7 +185,8 @@ define <2 x i16> @test_add_imm_1(<2 x i16> %a) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<2>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_add_imm_1_param_0]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_add_imm_1_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; NO-I16x2-NEXT: add.s16 %rs3, %rs2, 2; ; NO-I16x2-NEXT: add.s16 %rs4, %rs1, 1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -171,10 +202,12 @@ define <2 x i16> @test_sub(<2 x i16> %a, <2 x i16> %b) #0 { ; COMMON-NEXT: .reg .b32 %r<3>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_sub_param_0]; -; COMMON-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_sub_param_1]; -; COMMON-NEXT: sub.s16 %rs5, %rs2, %rs4; -; COMMON-NEXT: sub.s16 %rs6, %rs1, %rs3; +; COMMON-NEXT: ld.param.b32 %r2, [test_sub_param_1]; +; COMMON-NEXT: ld.param.b32 %r1, [test_sub_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; COMMON-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; COMMON-NEXT: sub.s16 %rs5, %rs4, %rs2; +; COMMON-NEXT: sub.s16 %rs6, %rs3, %rs1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; COMMON-NEXT: ret; %r = sub <2 x i16> %a, %b @@ -199,10 +232,12 @@ define <2 x i16> @test_smax(<2 x i16> %a, <2 x i16> %b) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<3>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_smax_param_0]; -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_smax_param_1]; -; NO-I16x2-NEXT: max.s16 %rs5, %rs2, %rs4; -; NO-I16x2-NEXT: max.s16 %rs6, %rs1, %rs3; +; NO-I16x2-NEXT: ld.param.b32 %r2, [test_smax_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_smax_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; NO-I16x2-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; NO-I16x2-NEXT: max.s16 %rs5, %rs4, %rs2; +; NO-I16x2-NEXT: max.s16 %rs6, %rs3, %rs1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; NO-I16x2-NEXT: ret; %cmp = icmp sgt <2 x i16> %a, %b @@ -228,10 +263,12 @@ define <2 x i16> @test_umax(<2 x i16> %a, <2 x i16> %b) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<3>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_umax_param_0]; -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_umax_param_1]; -; NO-I16x2-NEXT: max.u16 %rs5, %rs2, %rs4; -; NO-I16x2-NEXT: max.u16 %rs6, %rs1, %rs3; +; NO-I16x2-NEXT: ld.param.b32 %r2, [test_umax_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_umax_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; NO-I16x2-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; NO-I16x2-NEXT: max.u16 %rs5, %rs4, %rs2; +; NO-I16x2-NEXT: max.u16 %rs6, %rs3, %rs1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; NO-I16x2-NEXT: ret; %cmp = icmp ugt <2 x i16> %a, %b @@ -257,10 +294,12 @@ define <2 x i16> @test_smin(<2 x i16> %a, <2 x i16> %b) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<3>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_smin_param_0]; -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_smin_param_1]; -; NO-I16x2-NEXT: min.s16 %rs5, %rs2, %rs4; -; NO-I16x2-NEXT: min.s16 %rs6, %rs1, %rs3; +; NO-I16x2-NEXT: ld.param.b32 %r2, [test_smin_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_smin_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; NO-I16x2-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; NO-I16x2-NEXT: min.s16 %rs5, %rs4, %rs2; +; NO-I16x2-NEXT: min.s16 %rs6, %rs3, %rs1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; NO-I16x2-NEXT: ret; %cmp = icmp sle <2 x i16> %a, %b @@ -286,10 +325,12 @@ define <2 x i16> @test_umin(<2 x i16> %a, <2 x i16> %b) #0 { ; NO-I16x2-NEXT: .reg .b32 %r<3>; ; NO-I16x2-EMPTY: ; NO-I16x2-NEXT: // %bb.0: -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_umin_param_0]; -; NO-I16x2-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_umin_param_1]; -; NO-I16x2-NEXT: min.u16 %rs5, %rs2, %rs4; -; NO-I16x2-NEXT: min.u16 %rs6, %rs1, %rs3; +; NO-I16x2-NEXT: ld.param.b32 %r2, [test_umin_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_umin_param_0]; +; NO-I16x2-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; NO-I16x2-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; NO-I16x2-NEXT: min.u16 %rs5, %rs4, %rs2; +; NO-I16x2-NEXT: min.u16 %rs6, %rs3, %rs1; ; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; NO-I16x2-NEXT: ret; %cmp = icmp ule <2 x i16> %a, %b @@ -304,10 +345,12 @@ define <2 x i16> @test_mul(<2 x i16> %a, <2 x i16> %b) #0 { ; COMMON-NEXT: .reg .b32 %r<3>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_mul_param_0]; -; COMMON-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_mul_param_1]; -; COMMON-NEXT: mul.lo.s16 %rs5, %rs2, %rs4; -; COMMON-NEXT: mul.lo.s16 %rs6, %rs1, %rs3; +; COMMON-NEXT: ld.param.b32 %r2, [test_mul_param_1]; +; COMMON-NEXT: ld.param.b32 %r1, [test_mul_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; COMMON-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; COMMON-NEXT: mul.lo.s16 %rs5, %rs4, %rs2; +; COMMON-NEXT: mul.lo.s16 %rs6, %rs3, %rs1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; COMMON-NEXT: ret; %r = mul <2 x i16> %a, %b @@ -686,14 +729,18 @@ define <2 x i16> @test_select_cc(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x ; COMMON-NEXT: .reg .b32 %r<5>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_param_0]; -; COMMON-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_param_2]; -; COMMON-NEXT: ld.param.v2.b16 {%rs5, %rs6}, [test_select_cc_param_3]; -; COMMON-NEXT: setp.ne.b16 %p1, %rs3, %rs5; -; COMMON-NEXT: setp.ne.b16 %p2, %rs4, %rs6; -; COMMON-NEXT: ld.param.v2.b16 {%rs7, %rs8}, [test_select_cc_param_1]; -; COMMON-NEXT: selp.b16 %rs9, %rs2, %rs8, %p2; -; COMMON-NEXT: selp.b16 %rs10, %rs1, %rs7, %p1; +; COMMON-NEXT: ld.param.b32 %r4, [test_select_cc_param_3]; +; COMMON-NEXT: ld.param.b32 %r3, [test_select_cc_param_2]; +; COMMON-NEXT: ld.param.b32 %r2, [test_select_cc_param_1]; +; COMMON-NEXT: ld.param.b32 %r1, [test_select_cc_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r4; +; COMMON-NEXT: mov.b32 {%rs3, %rs4}, %r3; +; COMMON-NEXT: setp.ne.b16 %p1, %rs3, %rs1; +; COMMON-NEXT: setp.ne.b16 %p2, %rs4, %rs2; +; COMMON-NEXT: mov.b32 {%rs5, %rs6}, %r2; +; COMMON-NEXT: mov.b32 {%rs7, %rs8}, %r1; +; COMMON-NEXT: selp.b16 %rs9, %rs8, %rs6, %p2; +; COMMON-NEXT: selp.b16 %rs10, %rs7, %rs5, %p1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs10, %rs9}; ; COMMON-NEXT: ret; %cc = icmp ne <2 x i16> %c, %d @@ -711,10 +758,12 @@ define <2 x i32> @test_select_cc_i32_i16(<2 x i32> %a, <2 x i32> %b, ; COMMON-NEXT: // %bb.0: ; COMMON-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_i32_i16_param_1]; ; COMMON-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_select_cc_i32_i16_param_0]; -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_i32_i16_param_2]; -; COMMON-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_i32_i16_param_3]; -; COMMON-NEXT: setp.ne.b16 %p1, %rs1, %rs3; -; COMMON-NEXT: setp.ne.b16 %p2, %rs2, %rs4; +; COMMON-NEXT: ld.param.b32 %r6, [test_select_cc_i32_i16_param_3]; +; COMMON-NEXT: ld.param.b32 %r5, [test_select_cc_i32_i16_param_2]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r6; +; COMMON-NEXT: mov.b32 {%rs3, %rs4}, %r5; +; COMMON-NEXT: setp.ne.b16 %p1, %rs3, %rs1; +; COMMON-NEXT: setp.ne.b16 %p2, %rs4, %rs2; ; COMMON-NEXT: selp.b32 %r7, %r2, %r4, %p2; ; COMMON-NEXT: selp.b32 %r8, %r1, %r3, %p1; ; COMMON-NEXT: st.param.v2.b32 [func_retval0], {%r8, %r7}; @@ -735,12 +784,14 @@ define <2 x i16> @test_select_cc_i16_i32(<2 x i16> %a, <2 x i16> %b, ; COMMON-NEXT: // %bb.0: ; COMMON-NEXT: ld.param.v2.b32 {%r5, %r6}, [test_select_cc_i16_i32_param_3]; ; COMMON-NEXT: ld.param.v2.b32 {%r3, %r4}, [test_select_cc_i16_i32_param_2]; -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_select_cc_i16_i32_param_0]; +; COMMON-NEXT: ld.param.b32 %r2, [test_select_cc_i16_i32_param_1]; +; COMMON-NEXT: ld.param.b32 %r1, [test_select_cc_i16_i32_param_0]; ; COMMON-NEXT: setp.ne.b32 %p1, %r3, %r5; ; COMMON-NEXT: setp.ne.b32 %p2, %r4, %r6; -; COMMON-NEXT: ld.param.v2.b16 {%rs3, %rs4}, [test_select_cc_i16_i32_param_1]; -; COMMON-NEXT: selp.b16 %rs5, %rs2, %rs4, %p2; -; COMMON-NEXT: selp.b16 %rs6, %rs1, %rs3, %p1; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; COMMON-NEXT: mov.b32 {%rs3, %rs4}, %r1; +; COMMON-NEXT: selp.b16 %rs5, %rs4, %rs2, %p2; +; COMMON-NEXT: selp.b16 %rs6, %rs3, %rs1, %p1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs6, %rs5}; ; COMMON-NEXT: ret; <2 x i32> %c, <2 x i32> %d) #0 { @@ -851,7 +902,8 @@ define <2 x i32> @test_zext_2xi32(<2 x i16> %a) #0 { ; COMMON-NEXT: .reg .b32 %r<4>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_zext_2xi32_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_zext_2xi32_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: cvt.u32.u16 %r2, %rs2; ; COMMON-NEXT: cvt.u32.u16 %r3, %rs1; ; COMMON-NEXT: st.param.v2.b32 [func_retval0], {%r3, %r2}; @@ -868,7 +920,8 @@ define <2 x i64> @test_zext_2xi64(<2 x i16> %a) #0 { ; COMMON-NEXT: .reg .b64 %rd<3>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_zext_2xi64_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_zext_2xi64_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: cvt.u64.u16 %rd1, %rs2; ; COMMON-NEXT: cvt.u64.u16 %rd2, %rs1; ; COMMON-NEXT: st.param.v2.b64 [func_retval0], {%rd2, %rd1}; @@ -926,7 +979,8 @@ define <2 x i16> @test_shufflevector(<2 x i16> %a) #0 { ; COMMON-NEXT: .reg .b32 %r<2>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_shufflevector_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_shufflevector_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; ; COMMON-NEXT: ret; %s = shufflevector <2 x i16> %a, <2 x i16> undef, <2 x i32> @@ -934,16 +988,29 @@ define <2 x i16> @test_shufflevector(<2 x i16> %a) #0 { } define <2 x i16> @test_insertelement(<2 x i16> %a, i16 %x) #0 { -; COMMON-LABEL: test_insertelement( -; COMMON: { -; COMMON-NEXT: .reg .b16 %rs<4>; -; COMMON-NEXT: .reg .b32 %r<2>; -; COMMON-EMPTY: -; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.b16 %rs1, [test_insertelement_param_1]; -; COMMON-NEXT: ld.param.v2.b16 {%rs2, %rs3}, [test_insertelement_param_0]; -; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; -; COMMON-NEXT: ret; +; I16x2-LABEL: test_insertelement( +; I16x2: { +; I16x2-NEXT: .reg .b16 %rs<3>; +; I16x2-NEXT: .reg .b32 %r<2>; +; I16x2-EMPTY: +; I16x2-NEXT: // %bb.0: +; I16x2-NEXT: ld.param.b16 %rs1, [test_insertelement_param_1]; +; I16x2-NEXT: ld.param.b32 %r1, [test_insertelement_param_0]; +; I16x2-NEXT: mov.b32 {%rs2, _}, %r1; +; I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; +; I16x2-NEXT: ret; +; +; NO-I16x2-LABEL: test_insertelement( +; NO-I16x2: { +; NO-I16x2-NEXT: .reg .b16 %rs<3>; +; NO-I16x2-NEXT: .reg .b32 %r<2>; +; NO-I16x2-EMPTY: +; NO-I16x2-NEXT: // %bb.0: +; NO-I16x2-NEXT: ld.param.b16 %rs1, [test_insertelement_param_1]; +; NO-I16x2-NEXT: ld.param.b32 %r1, [test_insertelement_param_0]; +; NO-I16x2-NEXT: { .reg .b16 tmp; mov.b32 {%rs2, tmp}, %r1; } +; NO-I16x2-NEXT: st.param.v2.b16 [func_retval0], {%rs2, %rs1}; +; NO-I16x2-NEXT: ret; %i = insertelement <2 x i16> %a, i16 %x, i64 1 ret <2 x i16> %i } @@ -955,7 +1022,8 @@ define <2 x i16> @test_fptosi_2xhalf_to_2xi16(<2 x half> %a) #0 { ; COMMON-NEXT: .reg .b32 %r<2>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptosi_2xhalf_to_2xi16_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_fptosi_2xhalf_to_2xi16_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: cvt.rzi.s16.f16 %rs3, %rs2; ; COMMON-NEXT: cvt.rzi.s16.f16 %rs4, %rs1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; @@ -971,7 +1039,8 @@ define <2 x i16> @test_fptoui_2xhalf_to_2xi16(<2 x half> %a) #0 { ; COMMON-NEXT: .reg .b32 %r<2>; ; COMMON-EMPTY: ; COMMON-NEXT: // %bb.0: -; COMMON-NEXT: ld.param.v2.b16 {%rs1, %rs2}, [test_fptoui_2xhalf_to_2xi16_param_0]; +; COMMON-NEXT: ld.param.b32 %r1, [test_fptoui_2xhalf_to_2xi16_param_0]; +; COMMON-NEXT: mov.b32 {%rs1, %rs2}, %r1; ; COMMON-NEXT: cvt.rzi.u16.f16 %rs3, %rs2; ; COMMON-NEXT: cvt.rzi.u16.f16 %rs4, %rs1; ; COMMON-NEXT: st.param.v2.b16 [func_retval0], {%rs4, %rs3}; diff --git a/llvm/test/CodeGen/NVPTX/i8x4-instructions.ll b/llvm/test/CodeGen/NVPTX/i8x4-instructions.ll index 410c0019c7222..6a76cd15c3219 100644 --- a/llvm/test/CodeGen/NVPTX/i8x4-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/i8x4-instructions.ll @@ -1220,16 +1220,18 @@ define <4 x i8> @test_fptosi_4xhalf_to_4xi8(<4 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<12>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b16 {%rs1, %rs2, %rs3, %rs4}, [test_fptosi_4xhalf_to_4xi8_param_0]; -; CHECK-NEXT: cvt.rzi.s16.f16 %rs5, %rs4; -; CHECK-NEXT: cvt.rzi.s16.f16 %rs6, %rs3; -; CHECK-NEXT: mov.b32 %r3, {%rs6, %rs5}; -; CHECK-NEXT: mov.b32 {%rs7, %rs8}, %r3; -; CHECK-NEXT: cvt.u32.u16 %r4, %rs8; -; CHECK-NEXT: cvt.u32.u16 %r5, %rs7; +; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptosi_4xhalf_to_4xi8_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.rzi.s16.f16 %rs3, %rs2; +; CHECK-NEXT: cvt.rzi.s16.f16 %rs4, %rs1; +; CHECK-NEXT: mov.b32 %r3, {%rs4, %rs3}; +; CHECK-NEXT: mov.b32 {%rs5, %rs6}, %r3; +; CHECK-NEXT: cvt.u32.u16 %r4, %rs6; +; CHECK-NEXT: cvt.u32.u16 %r5, %rs5; ; CHECK-NEXT: prmt.b32 %r6, %r5, %r4, 0x3340U; -; CHECK-NEXT: cvt.rzi.s16.f16 %rs9, %rs2; -; CHECK-NEXT: cvt.rzi.s16.f16 %rs10, %rs1; +; CHECK-NEXT: mov.b32 {%rs7, %rs8}, %r1; +; CHECK-NEXT: cvt.rzi.s16.f16 %rs9, %rs8; +; CHECK-NEXT: cvt.rzi.s16.f16 %rs10, %rs7; ; CHECK-NEXT: mov.b32 %r7, {%rs10, %rs9}; ; CHECK-NEXT: mov.b32 {%rs11, %rs12}, %r7; ; CHECK-NEXT: cvt.u32.u16 %r8, %rs12; @@ -1249,16 +1251,18 @@ define <4 x i8> @test_fptoui_4xhalf_to_4xi8(<4 x half> %a) #0 { ; CHECK-NEXT: .reg .b32 %r<12>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b16 {%rs1, %rs2, %rs3, %rs4}, [test_fptoui_4xhalf_to_4xi8_param_0]; -; CHECK-NEXT: cvt.rzi.u16.f16 %rs5, %rs4; -; CHECK-NEXT: cvt.rzi.u16.f16 %rs6, %rs3; -; CHECK-NEXT: mov.b32 %r3, {%rs6, %rs5}; -; CHECK-NEXT: mov.b32 {%rs7, %rs8}, %r3; -; CHECK-NEXT: cvt.u32.u16 %r4, %rs8; -; CHECK-NEXT: cvt.u32.u16 %r5, %rs7; +; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [test_fptoui_4xhalf_to_4xi8_param_0]; +; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r2; +; CHECK-NEXT: cvt.rzi.u16.f16 %rs3, %rs2; +; CHECK-NEXT: cvt.rzi.u16.f16 %rs4, %rs1; +; CHECK-NEXT: mov.b32 %r3, {%rs4, %rs3}; +; CHECK-NEXT: mov.b32 {%rs5, %rs6}, %r3; +; CHECK-NEXT: cvt.u32.u16 %r4, %rs6; +; CHECK-NEXT: cvt.u32.u16 %r5, %rs5; ; CHECK-NEXT: prmt.b32 %r6, %r5, %r4, 0x3340U; -; CHECK-NEXT: cvt.rzi.u16.f16 %rs9, %rs2; -; CHECK-NEXT: cvt.rzi.u16.f16 %rs10, %rs1; +; CHECK-NEXT: mov.b32 {%rs7, %rs8}, %r1; +; CHECK-NEXT: cvt.rzi.u16.f16 %rs9, %rs8; +; CHECK-NEXT: cvt.rzi.u16.f16 %rs10, %rs7; ; CHECK-NEXT: mov.b32 %r7, {%rs10, %rs9}; ; CHECK-NEXT: mov.b32 {%rs11, %rs12}, %r7; ; CHECK-NEXT: cvt.u32.u16 %r8, %rs12; diff --git a/llvm/test/CodeGen/NVPTX/pr126337.ll b/llvm/test/CodeGen/NVPTX/pr126337.ll new file mode 100644 index 0000000000000..32e411584b0e5 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/pr126337.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_70 | FileCheck %s +; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64 -mcpu=sm_70 | %ptxas-verify %} + +; This IR should compile without triggering assertions in LICM +; when the CopyToReg from %0 in the first BB gets eliminated +; but we still use its result in the second BB. +; Technically the problem happens in MIR, but there are multiple +; passes involved, so testing with the IR reproducer is more convenient. +; https://github.com/llvm/llvm-project/pull/126337#issuecomment-3081431594 + +target datalayout = "e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64" +target triple = "nvptx64-nvidia-cuda" + +define ptx_kernel void @Equal_GPU_DT_COMPLEX64_DT_BOOL_kernel(<2 x float> %0) { +; CHECK-LABEL: Equal_GPU_DT_COMPLEX64_DT_BOOL_kernel( +; CHECK: { +; CHECK-NEXT: .reg .pred %p<2>; +; CHECK-NEXT: .reg .b16 %rs<2>; +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-NEXT: .reg .b64 %rd<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: // %.preheader15 +; CHECK-NEXT: ld.param.b64 %rd1, [Equal_GPU_DT_COMPLEX64_DT_BOOL_kernel_param_0]; +; CHECK-NEXT: { .reg .b32 tmp; mov.b64 {%r1, tmp}, %rd1; } +; CHECK-NEXT: setp.eq.f32 %p1, %r1, 0f00000000; +; CHECK-NEXT: selp.b16 %rs1, 1, 0, %p1; +; CHECK-NEXT: $L__BB0_1: // =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: mov.b64 %rd2, 0; +; CHECK-NEXT: st.b8 [%rd2], %rs1; +; CHECK-NEXT: bra.uni $L__BB0_1; +.preheader15: + br label %1 + +1: ; preds = %1, %.preheader15 + %2 = fcmp oeq <2 x float> %0, zeroinitializer + %3 = extractelement <2 x i1> %2, i64 0 + store i1 %3, ptr null, align 4 + br label %1 +} + diff --git a/llvm/test/CodeGen/NVPTX/reduction-intrinsics.ll b/llvm/test/CodeGen/NVPTX/reduction-intrinsics.ll index 87f965c84b6b6..92cb51b17f0c8 100644 --- a/llvm/test/CodeGen/NVPTX/reduction-intrinsics.ll +++ b/llvm/test/CodeGen/NVPTX/reduction-intrinsics.ll @@ -117,16 +117,20 @@ define float @reduce_fadd_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fadd_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fadd_float_param_0]; -; CHECK-NEXT: add.rn.f32 %r9, %r5, 0f00000000; -; CHECK-NEXT: add.rn.f32 %r10, %r9, %r6; -; CHECK-NEXT: add.rn.f32 %r11, %r10, %r7; -; CHECK-NEXT: add.rn.f32 %r12, %r11, %r8; -; CHECK-NEXT: add.rn.f32 %r13, %r12, %r1; -; CHECK-NEXT: add.rn.f32 %r14, %r13, %r2; -; CHECK-NEXT: add.rn.f32 %r15, %r14, %r3; -; CHECK-NEXT: add.rn.f32 %r16, %r15, %r4; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fadd_float_param_0+16]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd3; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fadd_float_param_0]; +; CHECK-NEXT: mov.b64 {%r5, %r6}, %rd2; +; CHECK-NEXT: mov.b64 {%r7, %r8}, %rd1; +; CHECK-NEXT: add.rn.f32 %r9, %r7, 0f00000000; +; CHECK-NEXT: add.rn.f32 %r10, %r9, %r8; +; CHECK-NEXT: add.rn.f32 %r11, %r10, %r5; +; CHECK-NEXT: add.rn.f32 %r12, %r11, %r6; +; CHECK-NEXT: add.rn.f32 %r13, %r12, %r3; +; CHECK-NEXT: add.rn.f32 %r14, %r13, %r4; +; CHECK-NEXT: add.rn.f32 %r15, %r14, %r1; +; CHECK-NEXT: add.rn.f32 %r16, %r15, %r2; ; CHECK-NEXT: st.param.b32 [func_retval0], %r16; ; CHECK-NEXT: ret; %res = call float @llvm.vector.reduce.fadd(float 0.0, <8 x float> %in) @@ -140,14 +144,18 @@ define float @reduce_fadd_float_reassoc(<8 x float> %in) { ; CHECK-SM80-NEXT: .reg .b64 %rd<5>; ; CHECK-SM80-EMPTY: ; CHECK-SM80-NEXT: // %bb.0: -; CHECK-SM80-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fadd_float_reassoc_param_0+16]; -; CHECK-SM80-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fadd_float_reassoc_param_0]; -; CHECK-SM80-NEXT: add.rn.f32 %r9, %r7, %r3; -; CHECK-SM80-NEXT: add.rn.f32 %r10, %r5, %r1; -; CHECK-SM80-NEXT: add.rn.f32 %r11, %r8, %r4; -; CHECK-SM80-NEXT: add.rn.f32 %r12, %r6, %r2; +; CHECK-SM80-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fadd_float_reassoc_param_0+16]; +; CHECK-SM80-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fadd_float_reassoc_param_0]; +; CHECK-SM80-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-SM80-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-SM80-NEXT: add.rn.f32 %r5, %r3, %r1; +; CHECK-SM80-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-SM80-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-SM80-NEXT: add.rn.f32 %r10, %r8, %r6; +; CHECK-SM80-NEXT: add.rn.f32 %r11, %r4, %r2; +; CHECK-SM80-NEXT: add.rn.f32 %r12, %r9, %r7; ; CHECK-SM80-NEXT: add.rn.f32 %r13, %r12, %r11; -; CHECK-SM80-NEXT: add.rn.f32 %r14, %r10, %r9; +; CHECK-SM80-NEXT: add.rn.f32 %r14, %r10, %r5; ; CHECK-SM80-NEXT: add.rn.f32 %r15, %r14, %r13; ; CHECK-SM80-NEXT: add.rn.f32 %r16, %r15, 0f00000000; ; CHECK-SM80-NEXT: st.param.b32 [func_retval0], %r16; @@ -321,15 +329,19 @@ define float @reduce_fmul_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmul_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmul_float_param_0]; -; CHECK-NEXT: mul.rn.f32 %r9, %r5, %r6; -; CHECK-NEXT: mul.rn.f32 %r10, %r9, %r7; -; CHECK-NEXT: mul.rn.f32 %r11, %r10, %r8; -; CHECK-NEXT: mul.rn.f32 %r12, %r11, %r1; -; CHECK-NEXT: mul.rn.f32 %r13, %r12, %r2; -; CHECK-NEXT: mul.rn.f32 %r14, %r13, %r3; -; CHECK-NEXT: mul.rn.f32 %r15, %r14, %r4; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmul_float_param_0+16]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd3; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmul_float_param_0]; +; CHECK-NEXT: mov.b64 {%r5, %r6}, %rd2; +; CHECK-NEXT: mov.b64 {%r7, %r8}, %rd1; +; CHECK-NEXT: mul.rn.f32 %r9, %r7, %r8; +; CHECK-NEXT: mul.rn.f32 %r10, %r9, %r5; +; CHECK-NEXT: mul.rn.f32 %r11, %r10, %r6; +; CHECK-NEXT: mul.rn.f32 %r12, %r11, %r3; +; CHECK-NEXT: mul.rn.f32 %r13, %r12, %r4; +; CHECK-NEXT: mul.rn.f32 %r14, %r13, %r1; +; CHECK-NEXT: mul.rn.f32 %r15, %r14, %r2; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; ; CHECK-NEXT: ret; %res = call float @llvm.vector.reduce.fmul(float 1.0, <8 x float> %in) @@ -343,14 +355,18 @@ define float @reduce_fmul_float_reassoc(<8 x float> %in) { ; CHECK-SM80-NEXT: .reg .b64 %rd<5>; ; CHECK-SM80-EMPTY: ; CHECK-SM80-NEXT: // %bb.0: -; CHECK-SM80-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmul_float_reassoc_param_0+16]; -; CHECK-SM80-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmul_float_reassoc_param_0]; -; CHECK-SM80-NEXT: mul.rn.f32 %r9, %r7, %r3; -; CHECK-SM80-NEXT: mul.rn.f32 %r10, %r5, %r1; -; CHECK-SM80-NEXT: mul.rn.f32 %r11, %r8, %r4; -; CHECK-SM80-NEXT: mul.rn.f32 %r12, %r6, %r2; +; CHECK-SM80-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmul_float_reassoc_param_0+16]; +; CHECK-SM80-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmul_float_reassoc_param_0]; +; CHECK-SM80-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-SM80-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-SM80-NEXT: mul.rn.f32 %r5, %r3, %r1; +; CHECK-SM80-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-SM80-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-SM80-NEXT: mul.rn.f32 %r10, %r8, %r6; +; CHECK-SM80-NEXT: mul.rn.f32 %r11, %r4, %r2; +; CHECK-SM80-NEXT: mul.rn.f32 %r12, %r9, %r7; ; CHECK-SM80-NEXT: mul.rn.f32 %r13, %r12, %r11; -; CHECK-SM80-NEXT: mul.rn.f32 %r14, %r10, %r9; +; CHECK-SM80-NEXT: mul.rn.f32 %r14, %r10, %r5; ; CHECK-SM80-NEXT: mul.rn.f32 %r15, %r14, %r13; ; CHECK-SM80-NEXT: st.param.b32 [func_retval0], %r15; ; CHECK-SM80-NEXT: ret; @@ -494,13 +510,17 @@ define float @reduce_fmax_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmax_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmax_float_param_0]; -; CHECK-NEXT: max.f32 %r9, %r8, %r4; -; CHECK-NEXT: max.f32 %r10, %r6, %r2; -; CHECK-NEXT: max.f32 %r11, %r10, %r9; -; CHECK-NEXT: max.f32 %r12, %r7, %r3; -; CHECK-NEXT: max.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmax_float_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmax_float_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: max.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: max.f32 %r10, %r9, %r7; +; CHECK-NEXT: max.f32 %r11, %r10, %r5; +; CHECK-NEXT: max.f32 %r12, %r3, %r1; +; CHECK-NEXT: max.f32 %r13, %r8, %r6; ; CHECK-NEXT: max.f32 %r14, %r13, %r12; ; CHECK-NEXT: max.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -517,13 +537,17 @@ define float @reduce_fmax_float_reassoc(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmax_float_reassoc_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmax_float_reassoc_param_0]; -; CHECK-NEXT: max.f32 %r9, %r8, %r4; -; CHECK-NEXT: max.f32 %r10, %r6, %r2; -; CHECK-NEXT: max.f32 %r11, %r10, %r9; -; CHECK-NEXT: max.f32 %r12, %r7, %r3; -; CHECK-NEXT: max.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmax_float_reassoc_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmax_float_reassoc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: max.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: max.f32 %r10, %r9, %r7; +; CHECK-NEXT: max.f32 %r11, %r10, %r5; +; CHECK-NEXT: max.f32 %r12, %r3, %r1; +; CHECK-NEXT: max.f32 %r13, %r8, %r6; ; CHECK-NEXT: max.f32 %r14, %r13, %r12; ; CHECK-NEXT: max.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -628,13 +652,17 @@ define float @reduce_fmin_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmin_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmin_float_param_0]; -; CHECK-NEXT: min.f32 %r9, %r8, %r4; -; CHECK-NEXT: min.f32 %r10, %r6, %r2; -; CHECK-NEXT: min.f32 %r11, %r10, %r9; -; CHECK-NEXT: min.f32 %r12, %r7, %r3; -; CHECK-NEXT: min.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmin_float_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmin_float_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: min.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: min.f32 %r10, %r9, %r7; +; CHECK-NEXT: min.f32 %r11, %r10, %r5; +; CHECK-NEXT: min.f32 %r12, %r3, %r1; +; CHECK-NEXT: min.f32 %r13, %r8, %r6; ; CHECK-NEXT: min.f32 %r14, %r13, %r12; ; CHECK-NEXT: min.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -651,13 +679,17 @@ define float @reduce_fmin_float_reassoc(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmin_float_reassoc_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmin_float_reassoc_param_0]; -; CHECK-NEXT: min.f32 %r9, %r8, %r4; -; CHECK-NEXT: min.f32 %r10, %r6, %r2; -; CHECK-NEXT: min.f32 %r11, %r10, %r9; -; CHECK-NEXT: min.f32 %r12, %r7, %r3; -; CHECK-NEXT: min.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmin_float_reassoc_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmin_float_reassoc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: min.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: min.f32 %r10, %r9, %r7; +; CHECK-NEXT: min.f32 %r11, %r10, %r5; +; CHECK-NEXT: min.f32 %r12, %r3, %r1; +; CHECK-NEXT: min.f32 %r13, %r8, %r6; ; CHECK-NEXT: min.f32 %r14, %r13, %r12; ; CHECK-NEXT: min.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -762,13 +794,17 @@ define float @reduce_fmaximum_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmaximum_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmaximum_float_param_0]; -; CHECK-NEXT: max.NaN.f32 %r9, %r8, %r4; -; CHECK-NEXT: max.NaN.f32 %r10, %r6, %r2; -; CHECK-NEXT: max.NaN.f32 %r11, %r10, %r9; -; CHECK-NEXT: max.NaN.f32 %r12, %r7, %r3; -; CHECK-NEXT: max.NaN.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmaximum_float_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmaximum_float_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: max.NaN.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: max.NaN.f32 %r10, %r9, %r7; +; CHECK-NEXT: max.NaN.f32 %r11, %r10, %r5; +; CHECK-NEXT: max.NaN.f32 %r12, %r3, %r1; +; CHECK-NEXT: max.NaN.f32 %r13, %r8, %r6; ; CHECK-NEXT: max.NaN.f32 %r14, %r13, %r12; ; CHECK-NEXT: max.NaN.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -785,13 +821,17 @@ define float @reduce_fmaximum_float_reassoc(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fmaximum_float_reassoc_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fmaximum_float_reassoc_param_0]; -; CHECK-NEXT: max.NaN.f32 %r9, %r8, %r4; -; CHECK-NEXT: max.NaN.f32 %r10, %r6, %r2; -; CHECK-NEXT: max.NaN.f32 %r11, %r10, %r9; -; CHECK-NEXT: max.NaN.f32 %r12, %r7, %r3; -; CHECK-NEXT: max.NaN.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fmaximum_float_reassoc_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fmaximum_float_reassoc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: max.NaN.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: max.NaN.f32 %r10, %r9, %r7; +; CHECK-NEXT: max.NaN.f32 %r11, %r10, %r5; +; CHECK-NEXT: max.NaN.f32 %r12, %r3, %r1; +; CHECK-NEXT: max.NaN.f32 %r13, %r8, %r6; ; CHECK-NEXT: max.NaN.f32 %r14, %r13, %r12; ; CHECK-NEXT: max.NaN.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -896,13 +936,17 @@ define float @reduce_fminimum_float(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fminimum_float_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fminimum_float_param_0]; -; CHECK-NEXT: min.NaN.f32 %r9, %r8, %r4; -; CHECK-NEXT: min.NaN.f32 %r10, %r6, %r2; -; CHECK-NEXT: min.NaN.f32 %r11, %r10, %r9; -; CHECK-NEXT: min.NaN.f32 %r12, %r7, %r3; -; CHECK-NEXT: min.NaN.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fminimum_float_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fminimum_float_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: min.NaN.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: min.NaN.f32 %r10, %r9, %r7; +; CHECK-NEXT: min.NaN.f32 %r11, %r10, %r5; +; CHECK-NEXT: min.NaN.f32 %r12, %r3, %r1; +; CHECK-NEXT: min.NaN.f32 %r13, %r8, %r6; ; CHECK-NEXT: min.NaN.f32 %r14, %r13, %r12; ; CHECK-NEXT: min.NaN.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; @@ -919,13 +963,17 @@ define float @reduce_fminimum_float_reassoc(<8 x float> %in) { ; CHECK-NEXT: .reg .b64 %rd<5>; ; CHECK-EMPTY: ; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [reduce_fminimum_float_reassoc_param_0+16]; -; CHECK-NEXT: ld.param.v4.b32 {%r5, %r6, %r7, %r8}, [reduce_fminimum_float_reassoc_param_0]; -; CHECK-NEXT: min.NaN.f32 %r9, %r8, %r4; -; CHECK-NEXT: min.NaN.f32 %r10, %r6, %r2; -; CHECK-NEXT: min.NaN.f32 %r11, %r10, %r9; -; CHECK-NEXT: min.NaN.f32 %r12, %r7, %r3; -; CHECK-NEXT: min.NaN.f32 %r13, %r5, %r1; +; CHECK-NEXT: ld.param.v2.b64 {%rd3, %rd4}, [reduce_fminimum_float_reassoc_param_0+16]; +; CHECK-NEXT: ld.param.v2.b64 {%rd1, %rd2}, [reduce_fminimum_float_reassoc_param_0]; +; CHECK-NEXT: mov.b64 {%r1, %r2}, %rd4; +; CHECK-NEXT: mov.b64 {%r3, %r4}, %rd2; +; CHECK-NEXT: min.NaN.f32 %r5, %r4, %r2; +; CHECK-NEXT: mov.b64 {%r6, %r7}, %rd3; +; CHECK-NEXT: mov.b64 {%r8, %r9}, %rd1; +; CHECK-NEXT: min.NaN.f32 %r10, %r9, %r7; +; CHECK-NEXT: min.NaN.f32 %r11, %r10, %r5; +; CHECK-NEXT: min.NaN.f32 %r12, %r3, %r1; +; CHECK-NEXT: min.NaN.f32 %r13, %r8, %r6; ; CHECK-NEXT: min.NaN.f32 %r14, %r13, %r12; ; CHECK-NEXT: min.NaN.f32 %r15, %r14, %r11; ; CHECK-NEXT: st.param.b32 [func_retval0], %r15; diff --git a/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir b/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir index 41e21248a3f0e..2796cdb3ae87d 100644 --- a/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir +++ b/llvm/test/CodeGen/PowerPC/NoCRFieldRedefWhenSpillingCRBIT.mir @@ -1,6 +1,12 @@ # RUN: llc -mcpu=pwr8 -mtriple=powerpc64le-unknown-linux-gnu -start-after \ # RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \ # RUN: -o - | FileCheck %s +# RUN: llc -mcpu=pwr9 -mtriple=powerpc64le-unknown-linux-gnu -start-after \ +# RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s +# RUN: llc -mcpu=pwr10 -mtriple=powerpc64le-unknown-linux-gnu -start-after \ +# RUN: virtregrewriter -ppc-asm-full-reg-names -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s --- | ; ModuleID = 'a.ll' @@ -30,7 +36,7 @@ ; Function Attrs: nounwind declare void @llvm.stackprotector(ptr, ptr) #1 - attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="none" "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"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "frame-pointer"="none" "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" } attributes #1 = { nounwind } !llvm.ident = !{!0} diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-arbitrary-sized-ints.ll b/llvm/test/CodeGen/PowerPC/aix-lower-arbitrary-sized-ints.ll new file mode 100644 index 0000000000000..c119da6e050a9 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-lower-arbitrary-sized-ints.ll @@ -0,0 +1,61 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc --verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK32 +; RUN: llc --verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK64 + +define ptr @lower_args(ptr %_0, i32 %0, i32 %1, i32 %2, i32 %3, ptr %4, ptr %5, i64 %6, i24 %7) { +; CHECK-LABEL: lower_args: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: blr +entry: + ret ptr %_0 +} + +define i32 @lower_args_withops_zeroext(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i24 %i) { +; CHECK32-LABEL: lower_args_withops_zeroext: +; CHECK32: # %bb.0: # %entry +; CHECK32-NEXT: lwz r3, 56(r1) +; CHECK32-NEXT: addi r3, r3, 255 +; CHECK32-NEXT: clrlwi r3, r3, 8 +; CHECK32-NEXT: blr +; +; CHECK64-LABEL: lower_args_withops_zeroext: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: lwz r3, 116(r1) +; CHECK64-NEXT: addi r3, r3, 255 +; CHECK64-NEXT: clrldi r3, r3, 40 +; CHECK64-NEXT: blr +entry: + %0 = add i24 %i, 255 + %1 = zext i24 %0 to i32 + ret i32 %1 +} + +define i32 @lower_args_withops_signext(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i24 signext %i) { +; CHECK32-LABEL: lower_args_withops_signext: +; CHECK32: # %bb.0: # %entry +; CHECK32-NEXT: lwz r3, 56(r1) +; CHECK32-NEXT: slwi r3, r3, 8 +; CHECK32-NEXT: srawi r3, r3, 8 +; CHECK32-NEXT: slwi r3, r3, 8 +; CHECK32-NEXT: addi r3, r3, 22272 +; CHECK32-NEXT: srawi r3, r3, 8 +; CHECK32-NEXT: blr +; +; CHECK64-LABEL: lower_args_withops_signext: +; CHECK64: # %bb.0: # %entry +; CHECK64-NEXT: lwz r3, 116(r1) +; CHECK64-NEXT: slwi r3, r3, 8 +; CHECK64-NEXT: srawi r3, r3, 8 +; CHECK64-NEXT: addi r3, r3, 87 +; CHECK64-NEXT: sldi r3, r3, 40 +; CHECK64-NEXT: sradi r3, r3, 40 +; CHECK64-NEXT: blr +entry: + %0 = add i24 %i, 87 + %1 = sext i24 %0 to i32 + ret i32 %1 +} diff --git a/llvm/test/CodeGen/PowerPC/froundeven-legalization.ll b/llvm/test/CodeGen/PowerPC/froundeven-legalization.ll new file mode 100644 index 0000000000000..238e200bfc782 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/froundeven-legalization.ll @@ -0,0 +1,111 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=powerpc64le < %s | FileCheck %s + +define void @test(ptr %p1, ptr %p2) nounwind { +; CHECK-LABEL: test: +; CHECK: # %bb.0: +; CHECK-NEXT: mflr 0 +; CHECK-NEXT: stdu 1, -224(1) +; CHECK-NEXT: li 5, 48 +; CHECK-NEXT: std 0, 240(1) +; CHECK-NEXT: std 27, 184(1) # 8-byte Folded Spill +; CHECK-NEXT: li 27, 16 +; CHECK-NEXT: std 28, 192(1) # 8-byte Folded Spill +; CHECK-NEXT: std 29, 200(1) # 8-byte Folded Spill +; CHECK-NEXT: li 29, 32 +; CHECK-NEXT: li 28, 48 +; CHECK-NEXT: stxvd2x 56, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 64 +; CHECK-NEXT: std 30, 208(1) # 8-byte Folded Spill +; CHECK-NEXT: mr 30, 4 +; CHECK-NEXT: stxvd2x 57, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 80 +; CHECK-NEXT: stxvd2x 58, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 96 +; CHECK-NEXT: lxvd2x 58, 0, 3 +; CHECK-NEXT: stxvd2x 59, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 112 +; CHECK-NEXT: lxvd2x 59, 3, 27 +; CHECK-NEXT: stxvd2x 60, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 128 +; CHECK-NEXT: stxvd2x 61, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 144 +; CHECK-NEXT: stxvd2x 62, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: li 5, 160 +; CHECK-NEXT: lxvd2x 62, 3, 28 +; CHECK-NEXT: stxvd2x 63, 1, 5 # 16-byte Folded Spill +; CHECK-NEXT: lxvd2x 63, 3, 29 +; CHECK-NEXT: xxswapd 57, 58 +; CHECK-NEXT: xxswapd 1, 59 +; CHECK-NEXT: xxswapd 60, 62 +; CHECK-NEXT: xxswapd 61, 63 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 56, 1 +; CHECK-NEXT: xxlor 1, 59, 59 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 0, 1 +; CHECK-NEXT: xxlor 1, 60, 60 +; CHECK-NEXT: xxmrgld 59, 0, 56 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 60, 1 +; CHECK-NEXT: xxlor 1, 62, 62 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 0, 1 +; CHECK-NEXT: xxlor 1, 61, 61 +; CHECK-NEXT: xxmrgld 62, 0, 60 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 61, 1 +; CHECK-NEXT: xxlor 1, 63, 63 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 0, 1 +; CHECK-NEXT: xxlor 1, 57, 57 +; CHECK-NEXT: xxmrgld 63, 0, 61 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: xxswapd 61, 1 +; CHECK-NEXT: xxlor 1, 58, 58 +; CHECK-NEXT: bl roundeven +; CHECK-NEXT: nop +; CHECK-NEXT: li 3, 160 +; CHECK-NEXT: stxvd2x 63, 30, 29 +; CHECK-NEXT: xxswapd 0, 1 +; CHECK-NEXT: stxvd2x 62, 30, 28 +; CHECK-NEXT: stxvd2x 59, 30, 27 +; CHECK-NEXT: ld 29, 200(1) # 8-byte Folded Reload +; CHECK-NEXT: ld 28, 192(1) # 8-byte Folded Reload +; CHECK-NEXT: ld 27, 184(1) # 8-byte Folded Reload +; CHECK-NEXT: lxvd2x 63, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 144 +; CHECK-NEXT: xxmrgld 0, 0, 61 +; CHECK-NEXT: lxvd2x 62, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 128 +; CHECK-NEXT: stxvd2x 0, 0, 30 +; CHECK-NEXT: ld 30, 208(1) # 8-byte Folded Reload +; CHECK-NEXT: lxvd2x 61, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 112 +; CHECK-NEXT: lxvd2x 60, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 96 +; CHECK-NEXT: lxvd2x 59, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 80 +; CHECK-NEXT: lxvd2x 58, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 64 +; CHECK-NEXT: lxvd2x 57, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: li 3, 48 +; CHECK-NEXT: lxvd2x 56, 1, 3 # 16-byte Folded Reload +; CHECK-NEXT: addi 1, 1, 224 +; CHECK-NEXT: ld 0, 16(1) +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr + %v = load <8 x double>, ptr %p1, align 64 + %res = call <8 x double> @llvm.roundeven.v8f64(<8 x double> %v) + store <8 x double> %res, ptr %p2, align 64 + ret void +} + +declare <8 x double> @llvm.roundeven.v8f64(<8 x double>) diff --git a/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll b/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll index 232014db9a012..a9503f77c3090 100644 --- a/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll +++ b/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll @@ -2,22 +2,87 @@ ; Verify whether the generated assembly for the following function includes the mtvsrbmi instruction. ; vector unsigned char v00FF() ; { -; vector unsigned char x = { 0xFF, 0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; -; return x; +; vector unsigned char x = { 0xFF, 0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; +; return x; +; } +; vector unsigned short short00FF() +; { +; vector unsigned short x = { 0xFF, 0,0,0, 0,0,0,0}; +; return x; +; } +; vector unsigned int int00FF() +; { +; vector unsigned int x = { 0xFF, 0,0,0}; +; return x; +; } +; vector unsigned long long longlong00FF() +; { +; vector unsigned long long x = { 0xFF, 0}; +; return x; ; } ; RUN: llc < %s -ppc-asm-full-reg-names -mtriple=powerpc-ibm-aix -mcpu=pwr10 -verify-machineinstrs \ -; RUN: | FileCheck %s --check-prefix=CHECK +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-BE + +; RUN: llc < %s -ppc-asm-full-reg-names -mtriple=powerpc64le-unknown-gnu-linux -mcpu=pwr10 -verify-machineinstrs \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-LE + +; CHECK-NOT: .byte 255 +; CHECK-NOT: .byte 0 define dso_local noundef range(i8 -1, 1) <16 x i8> @_Z5v00FFv() { -; CHECK-NOT: L..CPI0_0: -; CHECK-NOT: .byte 255 # 0xff -; CHECK-NOT: .byte 0 # 0x0 - -; CHECK-LABEL: _Z5v00FFv: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: mtvsrbmi v2, 1 -; CHECK-NEXT: blr +; CHECK-BE-LABEL: _Z5v00FFv: +; CHECK-BE: # %bb.0: # %entry +; CHECK-BE-NEXT: mtvsrbmi v2, 32768 +; CHECK-BE-NEXT: blr +; +; CHECK-LE-LABEL: _Z5v00FFv: +; CHECK-LE: # %bb.0: # %entry +; CHECK-LE-NEXT: mtvsrbmi v2, 1 +; CHECK-LE-NEXT: blr + entry: ret <16 x i8> } + +define dso_local noundef range(i16 0, 256) <8 x i16> @_Z9short00FFv() { +; CHECK-BE-LABEL: _Z9short00FFv: +; CHECK-BE: # %bb.0: # %entry +; CHECK-BE-NEXT: mtvsrbmi v2, 16384 +; CHECK-BE-NEXT: blr +; +; CHECK-LE-LABEL: _Z9short00FFv: +; CHECK-LE: # %bb.0: # %entry +; CHECK-LE-NEXT: mtvsrbmi v2, 1 +; CHECK-LE-NEXT: blr +entry: + ret <8 x i16> +} + +define dso_local noundef range(i32 0, 256) <4 x i32> @_Z7int00FFv() { +; CHECK-BE-LABEL: _Z7int00FFv: +; CHECK-BE: # %bb.0: # %entry +; CHECK-BE-NEXT: mtvsrbmi v2, 4096 +; CHECK-BE-NEXT: blr +; +; CHECK-LE-LABEL: _Z7int00FFv: +; CHECK-LE: # %bb.0: # %entry +; CHECK-LE-NEXT: mtvsrbmi v2, 1 +; CHECK-LE-NEXT: blr +entry: + ret <4 x i32> +} + +define dso_local noundef range(i64 0, 256) <2 x i64> @_Z12longlong00FFv() { +; CHECK-BE-LABEL: _Z12longlong00FFv: +; CHECK-BE: # %bb.0: # %entry +; CHECK-BE-NEXT: mtvsrbmi v2, 256 +; CHECK-BE-NEXT: blr +; +; CHECK-LE-LABEL: _Z12longlong00FFv: +; CHECK-LE: # %bb.0: # %entry +; CHECK-LE-NEXT: mtvsrbmi v2, 1 +; CHECK-LE-NEXT: blr +entry: + ret <2 x i64> +} diff --git a/llvm/test/CodeGen/PowerPC/nofpclass.ll b/llvm/test/CodeGen/PowerPC/nofpclass.ll new file mode 100644 index 0000000000000..b08e810cd1cca --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/nofpclass.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s +; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +; TODO: Update this test after adding the proper expansion of nofpclass for +; ppc_fp128 to test with more masks and to demonstrate preserving nofpclass +; after legalization. + +define ppc_fp128 @f(ppc_fp128 nofpclass(nan) %s) { +; CHECK-LABEL: f: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: blr +entry: + ret ppc_fp128 %s +} diff --git a/llvm/test/CodeGen/PowerPC/ppc64-P9-vabsd.ll b/llvm/test/CodeGen/PowerPC/ppc64-P9-vabsd.ll index 821cfd00dcd07..b540948b20f75 100644 --- a/llvm/test/CodeGen/PowerPC/ppc64-P9-vabsd.ll +++ b/llvm/test/CodeGen/PowerPC/ppc64-P9-vabsd.ll @@ -764,8 +764,13 @@ define <16 x i8> @sub_absv_8_ext(<16 x i8> %a, <16 x i8> %b) local_unnamed_addr ; ; CHECK-PWR7-LABEL: sub_absv_8_ext: ; CHECK-PWR7: # %bb.0: # %entry -; CHECK-PWR7-NEXT: stdu r1, -448(r1) -; CHECK-PWR7-NEXT: .cfi_def_cfa_offset 448 +; CHECK-PWR7-NEXT: stdu r1, -512(r1) +; CHECK-PWR7-NEXT: .cfi_def_cfa_offset 512 +; CHECK-PWR7-NEXT: .cfi_offset r14, -144 +; CHECK-PWR7-NEXT: .cfi_offset r15, -136 +; CHECK-PWR7-NEXT: .cfi_offset r16, -128 +; CHECK-PWR7-NEXT: .cfi_offset r17, -120 +; CHECK-PWR7-NEXT: .cfi_offset r18, -112 ; CHECK-PWR7-NEXT: .cfi_offset r19, -104 ; CHECK-PWR7-NEXT: .cfi_offset r20, -96 ; CHECK-PWR7-NEXT: .cfi_offset r21, -88 @@ -778,258 +783,244 @@ define <16 x i8> @sub_absv_8_ext(<16 x i8> %a, <16 x i8> %b) local_unnamed_addr ; CHECK-PWR7-NEXT: .cfi_offset r28, -32 ; CHECK-PWR7-NEXT: .cfi_offset r29, -24 ; CHECK-PWR7-NEXT: .cfi_offset r30, -16 -; CHECK-PWR7-NEXT: addi r3, r1, 304 -; CHECK-PWR7-NEXT: std r19, 344(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r20, 352(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r21, 360(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r22, 368(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r23, 376(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r24, 384(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r25, 392(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r26, 400(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r27, 408(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r28, 416(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r29, 424(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: std r30, 432(r1) # 8-byte Folded Spill -; CHECK-PWR7-NEXT: stxvw4x v2, 0, r3 +; CHECK-PWR7-NEXT: .cfi_offset r31, -8 +; CHECK-PWR7-NEXT: .cfi_offset r2, -152 ; CHECK-PWR7-NEXT: addi r3, r1, 320 -; CHECK-PWR7-NEXT: lbz r7, 304(r1) -; CHECK-PWR7-NEXT: stxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: lbz r8, 320(r1) -; CHECK-PWR7-NEXT: lbz r9, 305(r1) -; CHECK-PWR7-NEXT: lbz r10, 321(r1) -; CHECK-PWR7-NEXT: lbz r26, 325(r1) -; CHECK-PWR7-NEXT: clrlwi r7, r7, 24 -; CHECK-PWR7-NEXT: clrlwi r8, r8, 24 -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: clrlwi r10, r10, 24 -; CHECK-PWR7-NEXT: lbz r11, 306(r1) -; CHECK-PWR7-NEXT: lbz r12, 322(r1) -; CHECK-PWR7-NEXT: lbz r23, 314(r1) -; CHECK-PWR7-NEXT: clrlwi r22, r26, 24 -; CHECK-PWR7-NEXT: lbz r26, 330(r1) -; CHECK-PWR7-NEXT: sub r8, r7, r8 -; CHECK-PWR7-NEXT: lbz r7, 315(r1) -; CHECK-PWR7-NEXT: sub r20, r9, r10 -; CHECK-PWR7-NEXT: lbz r9, 331(r1) -; CHECK-PWR7-NEXT: lbz r0, 307(r1) -; CHECK-PWR7-NEXT: lbz r30, 323(r1) -; CHECK-PWR7-NEXT: clrlwi r11, r11, 24 -; CHECK-PWR7-NEXT: clrlwi r12, r12, 24 -; CHECK-PWR7-NEXT: clrlwi r23, r23, 24 -; CHECK-PWR7-NEXT: clrlwi r21, r26, 24 -; CHECK-PWR7-NEXT: clrlwi r7, r7, 24 -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: clrlwi r0, r0, 24 -; CHECK-PWR7-NEXT: clrlwi r30, r30, 24 -; CHECK-PWR7-NEXT: lbz r29, 308(r1) -; CHECK-PWR7-NEXT: lbz r28, 324(r1) -; CHECK-PWR7-NEXT: lbz r27, 309(r1) -; CHECK-PWR7-NEXT: lbz r25, 310(r1) -; CHECK-PWR7-NEXT: lbz r24, 326(r1) -; CHECK-PWR7-NEXT: sub r19, r11, r12 -; CHECK-PWR7-NEXT: sub r11, r23, r21 -; CHECK-PWR7-NEXT: sub r9, r7, r9 -; CHECK-PWR7-NEXT: sub r26, r0, r30 -; CHECK-PWR7-NEXT: srawi r12, r11, 31 -; CHECK-PWR7-NEXT: srawi r0, r9, 31 -; CHECK-PWR7-NEXT: lbz r3, 312(r1) -; CHECK-PWR7-NEXT: clrlwi r29, r29, 24 -; CHECK-PWR7-NEXT: clrlwi r28, r28, 24 -; CHECK-PWR7-NEXT: clrlwi r27, r27, 24 -; CHECK-PWR7-NEXT: clrlwi r25, r25, 24 -; CHECK-PWR7-NEXT: clrlwi r24, r24, 24 -; CHECK-PWR7-NEXT: xor r11, r11, r12 -; CHECK-PWR7-NEXT: xor r9, r9, r0 -; CHECK-PWR7-NEXT: sub r28, r29, r28 -; CHECK-PWR7-NEXT: sub r30, r27, r22 -; CHECK-PWR7-NEXT: sub r29, r25, r24 -; CHECK-PWR7-NEXT: sub r27, r11, r12 -; CHECK-PWR7-NEXT: sub r24, r9, r0 -; CHECK-PWR7-NEXT: lbz r9, 316(r1) -; CHECK-PWR7-NEXT: lbz r11, 332(r1) -; CHECK-PWR7-NEXT: lbz r4, 328(r1) -; CHECK-PWR7-NEXT: lbz r5, 311(r1) -; CHECK-PWR7-NEXT: lbz r6, 327(r1) -; CHECK-PWR7-NEXT: clrlwi r11, r11, 24 -; CHECK-PWR7-NEXT: clrlwi r3, r3, 24 -; CHECK-PWR7-NEXT: clrlwi r4, r4, 24 -; CHECK-PWR7-NEXT: clrlwi r5, r5, 24 -; CHECK-PWR7-NEXT: clrlwi r6, r6, 24 -; CHECK-PWR7-NEXT: sub r3, r3, r4 +; CHECK-PWR7-NEXT: std r14, 368(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r15, 376(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r16, 384(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r17, 392(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r18, 400(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r19, 408(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r20, 416(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r21, 424(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r22, 432(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r23, 440(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r24, 448(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r25, 456(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r26, 464(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r27, 472(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r28, 480(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r29, 488(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r30, 496(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r31, 504(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: std r2, 360(r1) # 8-byte Folded Spill +; CHECK-PWR7-NEXT: stxvw4x v2, 0, r3 +; CHECK-PWR7-NEXT: lbz r3, 320(r1) +; CHECK-PWR7-NEXT: addi r4, r1, 336 +; CHECK-PWR7-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; CHECK-PWR7-NEXT: stxvw4x v3, 0, r4 +; CHECK-PWR7-NEXT: lbz r15, 334(r1) +; CHECK-PWR7-NEXT: lbz r14, 350(r1) +; CHECK-PWR7-NEXT: lbz r31, 335(r1) +; CHECK-PWR7-NEXT: lbz r2, 351(r1) +; CHECK-PWR7-NEXT: sub r15, r15, r14 +; CHECK-PWR7-NEXT: sub r14, r31, r2 +; CHECK-PWR7-NEXT: srawi r2, r14, 31 +; CHECK-PWR7-NEXT: xor r14, r14, r2 +; CHECK-PWR7-NEXT: lbz r3, 333(r1) +; CHECK-PWR7-NEXT: lbz r19, 331(r1) +; CHECK-PWR7-NEXT: lbz r18, 347(r1) +; CHECK-PWR7-NEXT: sub r19, r19, r18 +; CHECK-PWR7-NEXT: lbz r17, 332(r1) +; CHECK-PWR7-NEXT: lbz r16, 348(r1) +; CHECK-PWR7-NEXT: sub r17, r17, r16 +; CHECK-PWR7-NEXT: lbz r23, 329(r1) +; CHECK-PWR7-NEXT: sub r14, r14, r2 +; CHECK-PWR7-NEXT: lbz r2, 349(r1) +; CHECK-PWR7-NEXT: lbz r22, 345(r1) +; CHECK-PWR7-NEXT: lbz r4, 336(r1) +; CHECK-PWR7-NEXT: lbz r5, 321(r1) +; CHECK-PWR7-NEXT: lbz r6, 337(r1) +; CHECK-PWR7-NEXT: lbz r7, 322(r1) +; CHECK-PWR7-NEXT: lbz r8, 338(r1) +; CHECK-PWR7-NEXT: lbz r9, 323(r1) +; CHECK-PWR7-NEXT: lbz r10, 339(r1) +; CHECK-PWR7-NEXT: lbz r11, 324(r1) +; CHECK-PWR7-NEXT: lbz r12, 340(r1) +; CHECK-PWR7-NEXT: lbz r0, 325(r1) +; CHECK-PWR7-NEXT: lbz r30, 341(r1) +; CHECK-PWR7-NEXT: lbz r29, 326(r1) +; CHECK-PWR7-NEXT: lbz r28, 342(r1) +; CHECK-PWR7-NEXT: lbz r27, 327(r1) +; CHECK-PWR7-NEXT: lbz r26, 343(r1) +; CHECK-PWR7-NEXT: sub r3, r3, r2 +; CHECK-PWR7-NEXT: lbz r25, 328(r1) +; CHECK-PWR7-NEXT: lbz r24, 344(r1) +; CHECK-PWR7-NEXT: lbz r21, 330(r1) +; CHECK-PWR7-NEXT: lbz r20, 346(r1) ; CHECK-PWR7-NEXT: sub r5, r5, r6 -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: srawi r4, r3, 31 +; CHECK-PWR7-NEXT: srawi r18, r3, 31 +; CHECK-PWR7-NEXT: sub r7, r7, r8 +; CHECK-PWR7-NEXT: sub r9, r9, r10 +; CHECK-PWR7-NEXT: sub r11, r11, r12 +; CHECK-PWR7-NEXT: sub r0, r0, r30 +; CHECK-PWR7-NEXT: sub r29, r29, r28 +; CHECK-PWR7-NEXT: sub r27, r27, r26 +; CHECK-PWR7-NEXT: sub r25, r25, r24 +; CHECK-PWR7-NEXT: srawi r31, r15, 31 +; CHECK-PWR7-NEXT: ld r2, 360(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: xor r3, r3, r18 ; CHECK-PWR7-NEXT: srawi r6, r5, 31 -; CHECK-PWR7-NEXT: xor r3, r3, r4 -; CHECK-PWR7-NEXT: sldi r27, r27, 56 -; CHECK-PWR7-NEXT: xor r5, r5, r6 -; CHECK-PWR7-NEXT: sub r9, r9, r11 -; CHECK-PWR7-NEXT: sub r3, r3, r4 -; CHECK-PWR7-NEXT: sldi r24, r24, 56 +; CHECK-PWR7-NEXT: srawi r8, r7, 31 +; CHECK-PWR7-NEXT: srawi r10, r9, 31 +; CHECK-PWR7-NEXT: srawi r12, r11, 31 +; CHECK-PWR7-NEXT: srawi r30, r0, 31 +; CHECK-PWR7-NEXT: sub r3, r3, r18 +; CHECK-PWR7-NEXT: srawi r18, r19, 31 +; CHECK-PWR7-NEXT: srawi r28, r29, 31 +; CHECK-PWR7-NEXT: ld r16, 384(r1) # 8-byte Folded Reload ; CHECK-PWR7-NEXT: sldi r3, r3, 56 -; CHECK-PWR7-NEXT: srawi r11, r9, 31 -; CHECK-PWR7-NEXT: std r27, 208(r1) -; CHECK-PWR7-NEXT: sub r4, r5, r6 -; CHECK-PWR7-NEXT: std r27, 216(r1) -; CHECK-PWR7-NEXT: srawi r27, r29, 31 -; CHECK-PWR7-NEXT: lbz r10, 313(r1) -; CHECK-PWR7-NEXT: xor r9, r9, r11 -; CHECK-PWR7-NEXT: std r24, 224(r1) -; CHECK-PWR7-NEXT: lbz r22, 329(r1) -; CHECK-PWR7-NEXT: std r24, 232(r1) -; CHECK-PWR7-NEXT: srawi r24, r30, 31 -; CHECK-PWR7-NEXT: ld r21, 360(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: sub r23, r9, r11 -; CHECK-PWR7-NEXT: lbz r9, 317(r1) -; CHECK-PWR7-NEXT: lbz r11, 333(r1) -; CHECK-PWR7-NEXT: xor r29, r29, r27 -; CHECK-PWR7-NEXT: std r3, 176(r1) -; CHECK-PWR7-NEXT: std r3, 184(r1) -; CHECK-PWR7-NEXT: sldi r3, r4, 56 -; CHECK-PWR7-NEXT: sldi r23, r23, 56 -; CHECK-PWR7-NEXT: xor r30, r30, r24 -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: clrlwi r11, r11, 24 -; CHECK-PWR7-NEXT: sub r4, r30, r24 -; CHECK-PWR7-NEXT: ld r30, 432(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: std r3, 160(r1) -; CHECK-PWR7-NEXT: std r3, 168(r1) -; CHECK-PWR7-NEXT: sub r9, r9, r11 -; CHECK-PWR7-NEXT: sub r3, r29, r27 -; CHECK-PWR7-NEXT: std r23, 240(r1) -; CHECK-PWR7-NEXT: ld r29, 424(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: srawi r11, r9, 31 -; CHECK-PWR7-NEXT: std r23, 248(r1) -; CHECK-PWR7-NEXT: ld r27, 408(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: srawi r23, r28, 31 +; CHECK-PWR7-NEXT: srawi r26, r27, 31 +; CHECK-PWR7-NEXT: srawi r24, r25, 31 +; CHECK-PWR7-NEXT: xor r19, r19, r18 +; CHECK-PWR7-NEXT: xor r15, r15, r31 +; CHECK-PWR7-NEXT: xor r5, r5, r6 +; CHECK-PWR7-NEXT: std r3, 272(r1) +; CHECK-PWR7-NEXT: std r3, 280(r1) +; CHECK-PWR7-NEXT: srawi r3, r17, 31 +; CHECK-PWR7-NEXT: sub r19, r19, r18 +; CHECK-PWR7-NEXT: xor r7, r7, r8 +; CHECK-PWR7-NEXT: sub r15, r15, r31 +; CHECK-PWR7-NEXT: xor r17, r17, r3 +; CHECK-PWR7-NEXT: xor r9, r9, r10 +; CHECK-PWR7-NEXT: xor r11, r11, r12 +; CHECK-PWR7-NEXT: xor r0, r0, r30 +; CHECK-PWR7-NEXT: xor r29, r29, r28 +; CHECK-PWR7-NEXT: xor r27, r27, r26 +; CHECK-PWR7-NEXT: sub r3, r17, r3 +; CHECK-PWR7-NEXT: xor r25, r25, r24 +; CHECK-PWR7-NEXT: sub r25, r25, r24 +; CHECK-PWR7-NEXT: sub r27, r27, r26 +; CHECK-PWR7-NEXT: sub r29, r29, r28 ; CHECK-PWR7-NEXT: sldi r3, r3, 56 -; CHECK-PWR7-NEXT: xor r28, r28, r23 -; CHECK-PWR7-NEXT: xor r9, r9, r11 -; CHECK-PWR7-NEXT: std r3, 144(r1) -; CHECK-PWR7-NEXT: ld r24, 384(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: std r3, 152(r1) -; CHECK-PWR7-NEXT: sldi r3, r4, 56 -; CHECK-PWR7-NEXT: sub r25, r9, r11 -; CHECK-PWR7-NEXT: lbz r9, 318(r1) -; CHECK-PWR7-NEXT: lbz r11, 334(r1) -; CHECK-PWR7-NEXT: std r3, 128(r1) +; CHECK-PWR7-NEXT: sub r0, r0, r30 +; CHECK-PWR7-NEXT: sub r11, r11, r12 +; CHECK-PWR7-NEXT: sub r9, r9, r10 +; CHECK-PWR7-NEXT: sub r7, r7, r8 +; CHECK-PWR7-NEXT: sub r5, r5, r6 +; CHECK-PWR7-NEXT: sldi r14, r14, 56 +; CHECK-PWR7-NEXT: sldi r15, r15, 56 +; CHECK-PWR7-NEXT: ld r31, 504(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r3, 256(r1) +; CHECK-PWR7-NEXT: std r3, 264(r1) +; CHECK-PWR7-NEXT: sldi r3, r19, 56 ; CHECK-PWR7-NEXT: sldi r25, r25, 56 -; CHECK-PWR7-NEXT: std r3, 136(r1) -; CHECK-PWR7-NEXT: sub r3, r28, r23 +; CHECK-PWR7-NEXT: sldi r27, r27, 56 +; CHECK-PWR7-NEXT: std r3, 240(r1) +; CHECK-PWR7-NEXT: std r3, 248(r1) +; CHECK-PWR7-NEXT: sub r3, r23, r22 +; CHECK-PWR7-NEXT: srawi r23, r3, 31 +; CHECK-PWR7-NEXT: sub r22, r21, r20 +; CHECK-PWR7-NEXT: srawi r21, r22, 31 +; CHECK-PWR7-NEXT: sldi r29, r29, 56 +; CHECK-PWR7-NEXT: sldi r0, r0, 56 +; CHECK-PWR7-NEXT: sldi r11, r11, 56 +; CHECK-PWR7-NEXT: xor r3, r3, r23 +; CHECK-PWR7-NEXT: xor r22, r22, r21 +; CHECK-PWR7-NEXT: sldi r9, r9, 56 +; CHECK-PWR7-NEXT: sldi r7, r7, 56 +; CHECK-PWR7-NEXT: sldi r5, r5, 56 +; CHECK-PWR7-NEXT: ld r30, 496(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: ld r28, 480(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: sub r3, r3, r23 +; CHECK-PWR7-NEXT: sub r22, r22, r21 +; CHECK-PWR7-NEXT: std r14, 304(r1) +; CHECK-PWR7-NEXT: ld r26, 464(r1) # 8-byte Folded Reload ; CHECK-PWR7-NEXT: sldi r3, r3, 56 -; CHECK-PWR7-NEXT: std r3, 112(r1) -; CHECK-PWR7-NEXT: ld r28, 416(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: clrlwi r11, r11, 24 -; CHECK-PWR7-NEXT: clrlwi r10, r10, 24 -; CHECK-PWR7-NEXT: std r25, 256(r1) -; CHECK-PWR7-NEXT: std r25, 264(r1) -; CHECK-PWR7-NEXT: sub r9, r9, r11 -; CHECK-PWR7-NEXT: srawi r25, r26, 31 -; CHECK-PWR7-NEXT: xor r26, r26, r25 -; CHECK-PWR7-NEXT: ld r23, 376(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: srawi r11, r9, 31 -; CHECK-PWR7-NEXT: std r3, 120(r1) -; CHECK-PWR7-NEXT: sub r4, r26, r25 -; CHECK-PWR7-NEXT: clrlwi r22, r22, 24 -; CHECK-PWR7-NEXT: srawi r7, r8, 31 -; CHECK-PWR7-NEXT: sub r10, r10, r22 -; CHECK-PWR7-NEXT: ld r26, 400(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: xor r9, r9, r11 -; CHECK-PWR7-NEXT: sldi r3, r4, 56 -; CHECK-PWR7-NEXT: srawi r22, r10, 31 -; CHECK-PWR7-NEXT: xor r8, r8, r7 -; CHECK-PWR7-NEXT: xor r10, r10, r22 -; CHECK-PWR7-NEXT: sub r10, r10, r22 -; CHECK-PWR7-NEXT: ld r25, 392(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: sub r12, r9, r11 -; CHECK-PWR7-NEXT: lbz r9, 319(r1) -; CHECK-PWR7-NEXT: lbz r11, 335(r1) -; CHECK-PWR7-NEXT: std r3, 96(r1) -; CHECK-PWR7-NEXT: sldi r12, r12, 56 -; CHECK-PWR7-NEXT: std r3, 104(r1) -; CHECK-PWR7-NEXT: ld r22, 368(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: sldi r10, r10, 56 -; CHECK-PWR7-NEXT: std r10, 192(r1) -; CHECK-PWR7-NEXT: clrlwi r9, r9, 24 -; CHECK-PWR7-NEXT: clrlwi r11, r11, 24 -; CHECK-PWR7-NEXT: sub r9, r9, r11 -; CHECK-PWR7-NEXT: std r12, 272(r1) -; CHECK-PWR7-NEXT: std r12, 280(r1) -; CHECK-PWR7-NEXT: srawi r12, r19, 31 -; CHECK-PWR7-NEXT: xor r0, r19, r12 -; CHECK-PWR7-NEXT: ld r19, 344(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: sub r3, r0, r12 -; CHECK-PWR7-NEXT: srawi r11, r9, 31 -; CHECK-PWR7-NEXT: std r10, 200(r1) -; CHECK-PWR7-NEXT: xor r9, r9, r11 +; CHECK-PWR7-NEXT: sldi r22, r22, 56 +; CHECK-PWR7-NEXT: ld r24, 448(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: ld r23, 440(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r14, 312(r1) +; CHECK-PWR7-NEXT: std r15, 288(r1) +; CHECK-PWR7-NEXT: std r3, 208(r1) +; CHECK-PWR7-NEXT: std r3, 216(r1) +; CHECK-PWR7-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; CHECK-PWR7-NEXT: std r15, 296(r1) +; CHECK-PWR7-NEXT: ld r21, 424(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: ld r20, 416(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r22, 224(r1) +; CHECK-PWR7-NEXT: std r22, 232(r1) +; CHECK-PWR7-NEXT: sub r4, r3, r4 +; CHECK-PWR7-NEXT: std r25, 192(r1) +; CHECK-PWR7-NEXT: ld r22, 432(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: ld r19, 408(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: srawi r3, r4, 31 +; CHECK-PWR7-NEXT: std r25, 200(r1) +; CHECK-PWR7-NEXT: ld r25, 456(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r27, 176(r1) +; CHECK-PWR7-NEXT: std r27, 184(r1) +; CHECK-PWR7-NEXT: xor r4, r4, r3 +; CHECK-PWR7-NEXT: std r29, 160(r1) +; CHECK-PWR7-NEXT: ld r27, 472(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r29, 168(r1) +; CHECK-PWR7-NEXT: std r0, 144(r1) +; CHECK-PWR7-NEXT: sub r3, r4, r3 +; CHECK-PWR7-NEXT: std r0, 152(r1) +; CHECK-PWR7-NEXT: ld r29, 488(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: ld r18, 400(r1) # 8-byte Folded Reload ; CHECK-PWR7-NEXT: sldi r3, r3, 56 -; CHECK-PWR7-NEXT: sub r9, r9, r11 -; CHECK-PWR7-NEXT: std r3, 80(r1) -; CHECK-PWR7-NEXT: std r3, 88(r1) -; CHECK-PWR7-NEXT: sldi r9, r9, 56 -; CHECK-PWR7-NEXT: std r9, 288(r1) -; CHECK-PWR7-NEXT: std r9, 296(r1) -; CHECK-PWR7-NEXT: srawi r9, r20, 31 -; CHECK-PWR7-NEXT: xor r11, r20, r9 -; CHECK-PWR7-NEXT: ld r20, 352(r1) # 8-byte Folded Reload -; CHECK-PWR7-NEXT: sub r4, r11, r9 -; CHECK-PWR7-NEXT: sldi r3, r4, 56 +; CHECK-PWR7-NEXT: std r11, 128(r1) +; CHECK-PWR7-NEXT: ld r17, 392(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r11, 136(r1) +; CHECK-PWR7-NEXT: std r9, 112(r1) ; CHECK-PWR7-NEXT: std r3, 64(r1) ; CHECK-PWR7-NEXT: std r3, 72(r1) -; CHECK-PWR7-NEXT: sub r3, r8, r7 -; CHECK-PWR7-NEXT: sldi r3, r3, 56 -; CHECK-PWR7-NEXT: std r3, 48(r1) -; CHECK-PWR7-NEXT: std r3, 56(r1) -; CHECK-PWR7-NEXT: addi r3, r1, 288 +; CHECK-PWR7-NEXT: addi r3, r1, 304 +; CHECK-PWR7-NEXT: std r9, 120(r1) +; CHECK-PWR7-NEXT: ld r15, 376(r1) # 8-byte Folded Reload +; CHECK-PWR7-NEXT: std r7, 96(r1) +; CHECK-PWR7-NEXT: std r7, 104(r1) +; CHECK-PWR7-NEXT: std r5, 80(r1) +; CHECK-PWR7-NEXT: std r5, 88(r1) ; CHECK-PWR7-NEXT: lxvw4x v2, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 272 +; CHECK-PWR7-NEXT: addi r3, r1, 288 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 256 +; CHECK-PWR7-NEXT: addi r3, r1, 272 +; CHECK-PWR7-NEXT: ld r14, 368(r1) # 8-byte Folded Reload ; CHECK-PWR7-NEXT: vmrghb v2, v3, v2 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 240 +; CHECK-PWR7-NEXT: addi r3, r1, 256 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 224 +; CHECK-PWR7-NEXT: addi r3, r1, 240 ; CHECK-PWR7-NEXT: vmrghb v3, v4, v3 ; CHECK-PWR7-NEXT: vmrghh v2, v3, v2 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 208 +; CHECK-PWR7-NEXT: addi r3, r1, 224 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 192 +; CHECK-PWR7-NEXT: addi r3, r1, 208 ; CHECK-PWR7-NEXT: vmrghb v3, v4, v3 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 176 +; CHECK-PWR7-NEXT: addi r3, r1, 192 ; CHECK-PWR7-NEXT: lxvw4x v5, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 160 +; CHECK-PWR7-NEXT: addi r3, r1, 176 ; CHECK-PWR7-NEXT: vmrghb v4, v5, v4 ; CHECK-PWR7-NEXT: vmrghh v3, v4, v3 ; CHECK-PWR7-NEXT: xxmrghw vs0, v3, v2 ; CHECK-PWR7-NEXT: lxvw4x v2, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 144 +; CHECK-PWR7-NEXT: addi r3, r1, 160 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 128 +; CHECK-PWR7-NEXT: addi r3, r1, 144 ; CHECK-PWR7-NEXT: vmrghb v2, v3, v2 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 112 +; CHECK-PWR7-NEXT: addi r3, r1, 128 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 96 ; CHECK-PWR7-NEXT: vmrghb v3, v4, v3 +; CHECK-PWR7-NEXT: addi r3, r1, 112 ; CHECK-PWR7-NEXT: vmrghh v2, v3, v2 ; CHECK-PWR7-NEXT: lxvw4x v3, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 80 +; CHECK-PWR7-NEXT: addi r3, r1, 96 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 64 +; CHECK-PWR7-NEXT: addi r3, r1, 80 ; CHECK-PWR7-NEXT: vmrghb v3, v4, v3 ; CHECK-PWR7-NEXT: lxvw4x v4, 0, r3 -; CHECK-PWR7-NEXT: addi r3, r1, 48 +; CHECK-PWR7-NEXT: addi r3, r1, 64 ; CHECK-PWR7-NEXT: lxvw4x v5, 0, r3 ; CHECK-PWR7-NEXT: vmrghb v4, v5, v4 ; CHECK-PWR7-NEXT: vmrghh v3, v4, v3 ; CHECK-PWR7-NEXT: xxmrghw vs1, v3, v2 ; CHECK-PWR7-NEXT: xxmrghd v2, vs1, vs0 -; CHECK-PWR7-NEXT: addi r1, r1, 448 +; CHECK-PWR7-NEXT: addi r1, r1, 512 ; CHECK-PWR7-NEXT: blr entry: %vecext = extractelement <16 x i8> %a, i32 0 diff --git a/llvm/test/CodeGen/PowerPC/pr160040.ll b/llvm/test/CodeGen/PowerPC/pr160040.ll new file mode 100644 index 0000000000000..865239b37112c --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/pr160040.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s + +; Make sure this does not crash. +define i32 @test(i32 %arg) { +; CHECK-LABEL: test: +; CHECK: # %bb.0: +; CHECK-NEXT: rlwinm 4, 3, 13, 19, 19 +; CHECK-NEXT: rlwinm 3, 3, 2, 30, 30 +; CHECK-NEXT: xori 4, 4, 4096 +; CHECK-NEXT: xori 3, 3, 2 +; CHECK-NEXT: rlwimi 3, 4, 0, 31, 29 +; CHECK-NEXT: blr + %icmp = icmp sgt i32 %arg, -1 + %select = select i1 %icmp, i16 1, i16 0 + %select1 = select i1 %icmp, i16 16384, i16 0 + %lshr = lshr i16 %select1, 1 + %zext = zext i16 %lshr to i32 + %lshr2 = lshr i32 %zext, 1 + %shl = shl i16 %select, 1 + %zext3 = zext i16 %shl to i32 + %or = or i32 %lshr2, %zext3 + ret i32 %or +} diff --git a/llvm/test/CodeGen/PowerPC/tls-picgot.ll b/llvm/test/CodeGen/PowerPC/tls-picgot.ll new file mode 100644 index 0000000000000..6562d864d1ba7 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/tls-picgot.ll @@ -0,0 +1,31 @@ +; RUN: llc -verify-machineinstrs -relocation-model=pic < %s | FileCheck %s + +target triple = "powerpc-unknown-linux-gnu" + +; Test that LR is preserved when PPC32PICGOT clobbers it with a local "bl". + +@TLS = external thread_local global i8 + +; CHECK-LABEL: tls_addr: +; CHECK: mflr [[SAVED_REG:[0-9]+]] + +; CHECK: bl [[JUMP:\.L[[:alnum:]_]+]] +; CHECK-NEXT: [[OFFSET:\.L[[:alnum:]_]+]]: +; CHECK-NEXT: .long _GLOBAL_OFFSET_TABLE_-[[OFFSET]] +; CHECK-NEXT: [[JUMP]] +; CHECK-NEXT: mflr {{[0-9]+}} + +; CHECK: mtlr [[SAVED_REG]] +; CHECK-NEXT: blr + +define ptr @tls_addr() unnamed_addr { + %1 = call ptr @llvm.threadlocal.address.p0(ptr @TLS) + ret ptr %1 +} + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"PIC Level", i32 2} +!1 = !{i32 7, !"PIE Level", i32 2} diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll index b24ea9ec1561e..3c617f9854761 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/constbarrier-rv32.ll @@ -32,9 +32,12 @@ define void @constant_fold_barrier_i128(ptr %p) { ; RV32-NEXT: mv a6, a1 ; RV32-NEXT: seqz a7, a1 ; RV32-NEXT: and a1, a7, a1 +; RV32-NEXT: mv a1, a1 ; RV32-NEXT: mv a7, a1 ; RV32-NEXT: seqz a3, a1 ; RV32-NEXT: and a1, a3, a1 +; RV32-NEXT: mv a1, a1 +; RV32-NEXT: mv a1, a1 ; RV32-NEXT: sw a2, 0(a0) ; RV32-NEXT: sw a6, 4(a0) ; RV32-NEXT: sw a7, 8(a0) diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/div-by-constant.ll b/llvm/test/CodeGen/RISCV/GlobalISel/div-by-constant.ll index 4b999b892ed35..e4b599e418b70 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/div-by-constant.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/div-by-constant.ll @@ -103,15 +103,18 @@ define i64 @udiv64_constant_no_add(i64 %a) nounwind { ; RV32-NEXT: mulhu a1, a1, a2 ; RV32-NEXT: add a5, a5, a6 ; RV32-NEXT: mv t0, t1 +; RV32-NEXT: mv a1, a1 ; RV32-NEXT: sltu a4, a5, a6 ; RV32-NEXT: add a5, a5, a7 ; RV32-NEXT: sltu a6, t1, t1 ; RV32-NEXT: sltiu t1, t1, 0 ; RV32-NEXT: add t0, t0, t2 +; RV32-NEXT: mv a1, a1 ; RV32-NEXT: sltu a2, a5, a7 ; RV32-NEXT: add a6, a6, t1 ; RV32-NEXT: sltu a5, t0, t2 ; RV32-NEXT: add t0, t0, a0 +; RV32-NEXT: mv a1, a1 ; RV32-NEXT: add a2, a4, a2 ; RV32-NEXT: add a5, a6, a5 ; RV32-NEXT: sltu a0, t0, a0 @@ -155,6 +158,7 @@ define i64 @udiv64_constant_add(i64 %a) nounwind { ; RV32-NEXT: mulhu a7, a0, a2 ; RV32-NEXT: mulhu t2, a1, a3 ; RV32-NEXT: mv t1, t2 +; RV32-NEXT: mv t1, t1 ; RV32-NEXT: mul t2, a1, a3 ; RV32-NEXT: mulhu a2, a1, a2 ; RV32-NEXT: mulhu a3, a0, a3 diff --git a/llvm/test/CodeGen/RISCV/calling-conv-preserve-most.ll b/llvm/test/CodeGen/RISCV/calling-conv-preserve-most.ll new file mode 100644 index 0000000000000..08340bbe0013a --- /dev/null +++ b/llvm/test/CodeGen/RISCV/calling-conv-preserve-most.ll @@ -0,0 +1,449 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 < %s | FileCheck %s -check-prefix=RV32I +; RUN: llc -mtriple=riscv64 < %s | FileCheck %s -check-prefix=RV64I +; RUN: llc -mtriple=riscv32 -mattr=+e -target-abi ilp32e < %s | FileCheck %s -check-prefix=RV32E +; RUN: llc -mtriple=riscv64 -mattr=+e -target-abi lp64e < %s | FileCheck %s -check-prefix=RV64E + +; Check the PreserveMost calling convention works. + +declare void @standard_cc_func() +declare preserve_mostcc void @preserve_mostcc_func() + +define preserve_mostcc void @preserve_mostcc1() nounwind { +; RV32I-LABEL: preserve_mostcc1: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: addi sp, sp, -64 +; RV32I-NEXT: sw ra, 60(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw t0, 56(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a0, 52(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a1, 48(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a2, 44(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a3, 40(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a4, 36(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a5, 32(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a6, 28(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw a7, 24(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw t4, 20(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw t5, 16(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw t6, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: call standard_cc_func +; RV32I-NEXT: lw ra, 60(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw t0, 56(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a0, 52(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a1, 48(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a2, 44(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a3, 40(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a4, 36(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a5, 32(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a6, 28(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw a7, 24(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw t4, 20(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw t5, 16(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw t6, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 64 +; RV32I-NEXT: ret +; +; RV64I-LABEL: preserve_mostcc1: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: addi sp, sp, -112 +; RV64I-NEXT: sd ra, 104(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd t0, 96(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a0, 88(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a1, 80(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a2, 72(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a3, 64(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a4, 56(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a5, 48(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a6, 40(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd a7, 32(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd t4, 24(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd t5, 16(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd t6, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: call standard_cc_func +; RV64I-NEXT: ld ra, 104(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld t0, 96(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a0, 88(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a1, 80(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a2, 72(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a3, 64(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a4, 56(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a5, 48(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a6, 40(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld a7, 32(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld t4, 24(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld t5, 16(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld t6, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 112 +; RV64I-NEXT: ret +; +; RV32E-LABEL: preserve_mostcc1: +; RV32E: # %bb.0: # %entry +; RV32E-NEXT: addi sp, sp, -32 +; RV32E-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw t0, 24(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a0, 20(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a1, 16(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a2, 12(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a3, 8(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a4, 4(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw a5, 0(sp) # 4-byte Folded Spill +; RV32E-NEXT: call standard_cc_func +; RV32E-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw t0, 24(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a0, 20(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a1, 16(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a2, 12(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a3, 8(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a4, 4(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw a5, 0(sp) # 4-byte Folded Reload +; RV32E-NEXT: addi sp, sp, 32 +; RV32E-NEXT: ret +; +; RV64E-LABEL: preserve_mostcc1: +; RV64E: # %bb.0: # %entry +; RV64E-NEXT: addi sp, sp, -64 +; RV64E-NEXT: sd ra, 56(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd t0, 48(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a0, 40(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a1, 32(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a2, 24(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a3, 16(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a4, 8(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd a5, 0(sp) # 8-byte Folded Spill +; RV64E-NEXT: call standard_cc_func +; RV64E-NEXT: ld ra, 56(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld t0, 48(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a0, 40(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a1, 32(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a2, 24(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a3, 16(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a4, 8(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld a5, 0(sp) # 8-byte Folded Reload +; RV64E-NEXT: addi sp, sp, 64 +; RV64E-NEXT: ret +entry: + call void @standard_cc_func() + ret void +} + +define preserve_mostcc void @preserve_mostcc2() nounwind { +; RV32I-LABEL: preserve_mostcc2: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: call preserve_mostcc_func +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: preserve_mostcc2: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: call preserve_mostcc_func +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV32E-LABEL: preserve_mostcc2: +; RV32E: # %bb.0: +; RV32E-NEXT: addi sp, sp, -4 +; RV32E-NEXT: sw ra, 0(sp) # 4-byte Folded Spill +; RV32E-NEXT: call preserve_mostcc_func +; RV32E-NEXT: lw ra, 0(sp) # 4-byte Folded Reload +; RV32E-NEXT: addi sp, sp, 4 +; RV32E-NEXT: ret +; +; RV64E-LABEL: preserve_mostcc2: +; RV64E: # %bb.0: +; RV64E-NEXT: addi sp, sp, -8 +; RV64E-NEXT: sd ra, 0(sp) # 8-byte Folded Spill +; RV64E-NEXT: call preserve_mostcc_func +; RV64E-NEXT: ld ra, 0(sp) # 8-byte Folded Reload +; RV64E-NEXT: addi sp, sp, 8 +; RV64E-NEXT: ret + call preserve_mostcc void @preserve_mostcc_func() + ret void +} + +; X6, X7 and X28 will be saved to registers. +define void @preserve_mostcc3() nounwind { +; RV32I-LABEL: preserve_mostcc3: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv a0, t1 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv a1, t2 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv a2, t3 +; RV32I-NEXT: call preserve_mostcc_func +; RV32I-NEXT: mv t1, a0 +; RV32I-NEXT: mv t2, a1 +; RV32I-NEXT: mv t3, a2 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: preserve_mostcc3: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -32 +; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv a0, t1 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv a1, t2 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv a2, t3 +; RV64I-NEXT: call preserve_mostcc_func +; RV64I-NEXT: mv t1, a0 +; RV64I-NEXT: mv t2, a1 +; RV64I-NEXT: mv t3, a2 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 32 +; RV64I-NEXT: ret +; +; RV32E-LABEL: preserve_mostcc3: +; RV32E: # %bb.0: +; RV32E-NEXT: addi sp, sp, -12 +; RV32E-NEXT: sw ra, 8(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw s0, 4(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw s1, 0(sp) # 4-byte Folded Spill +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: mv a0, t1 +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: mv a1, t2 +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: mv a2, t3 +; RV32E-NEXT: call preserve_mostcc_func +; RV32E-NEXT: mv t1, a0 +; RV32E-NEXT: mv t2, a1 +; RV32E-NEXT: mv t3, a2 +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: lw ra, 8(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw s0, 4(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw s1, 0(sp) # 4-byte Folded Reload +; RV32E-NEXT: addi sp, sp, 12 +; RV32E-NEXT: ret +; +; RV64E-LABEL: preserve_mostcc3: +; RV64E: # %bb.0: +; RV64E-NEXT: addi sp, sp, -24 +; RV64E-NEXT: sd ra, 16(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd s0, 8(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd s1, 0(sp) # 8-byte Folded Spill +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: mv a0, t1 +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: mv a1, t2 +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: mv a2, t3 +; RV64E-NEXT: call preserve_mostcc_func +; RV64E-NEXT: mv t1, a0 +; RV64E-NEXT: mv t2, a1 +; RV64E-NEXT: mv t3, a2 +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: ld ra, 16(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld s0, 8(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld s1, 0(sp) # 8-byte Folded Reload +; RV64E-NEXT: addi sp, sp, 24 +; RV64E-NEXT: ret + %1 = call i32 asm sideeffect "", "={x6}"() nounwind + %2 = call i32 asm sideeffect "", "={x7}"() nounwind + %3 = call i32 asm sideeffect "", "={x8}"() nounwind + %4 = call i32 asm sideeffect "", "={x9}"() nounwind + %5 = call i32 asm sideeffect "", "={x28}"() nounwind + call preserve_mostcc void @preserve_mostcc_func() + call void asm sideeffect "", "{x6},{x7},{x8},{x9},{x28}"(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5) + ret void +} + +; X6, X7 and X28 will be saved to the stack. +define void @preserve_mostcc4() nounwind { +; RV32I-LABEL: preserve_mostcc4: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -32 +; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv s2, t1 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv s3, t2 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: mv s4, t3 +; RV32I-NEXT: call standard_cc_func +; RV32I-NEXT: mv t1, s2 +; RV32I-NEXT: mv t2, s3 +; RV32I-NEXT: mv t3, s4 +; RV32I-NEXT: #APP +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload +; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: ret +; +; RV64I-LABEL: preserve_mostcc4: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -48 +; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv s2, t1 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv s3, t2 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: mv s4, t3 +; RV64I-NEXT: call standard_cc_func +; RV64I-NEXT: mv t1, s2 +; RV64I-NEXT: mv t2, s3 +; RV64I-NEXT: mv t3, s4 +; RV64I-NEXT: #APP +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 48 +; RV64I-NEXT: ret +; +; RV32E-LABEL: preserve_mostcc4: +; RV32E: # %bb.0: +; RV32E-NEXT: addi sp, sp, -24 +; RV32E-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32E-NEXT: sw s1, 12(sp) # 4-byte Folded Spill +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: sw t1, 8(sp) # 4-byte Folded Spill +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: sw t2, 4(sp) # 4-byte Folded Spill +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: sw t3, 0(sp) # 4-byte Folded Spill +; RV32E-NEXT: call standard_cc_func +; RV32E-NEXT: lw t1, 8(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw t2, 4(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw t3, 0(sp) # 4-byte Folded Reload +; RV32E-NEXT: #APP +; RV32E-NEXT: #NO_APP +; RV32E-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32E-NEXT: lw s1, 12(sp) # 4-byte Folded Reload +; RV32E-NEXT: addi sp, sp, 24 +; RV32E-NEXT: ret +; +; RV64E-LABEL: preserve_mostcc4: +; RV64E: # %bb.0: +; RV64E-NEXT: addi sp, sp, -48 +; RV64E-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64E-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: sd t1, 16(sp) # 8-byte Folded Spill +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: sd t2, 8(sp) # 8-byte Folded Spill +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: sd t3, 0(sp) # 8-byte Folded Spill +; RV64E-NEXT: call standard_cc_func +; RV64E-NEXT: ld t1, 16(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld t2, 8(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld t3, 0(sp) # 8-byte Folded Reload +; RV64E-NEXT: #APP +; RV64E-NEXT: #NO_APP +; RV64E-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64E-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64E-NEXT: addi sp, sp, 48 +; RV64E-NEXT: ret + %1 = call i32 asm sideeffect "", "={x6}"() nounwind + %2 = call i32 asm sideeffect "", "={x7}"() nounwind + %3 = call i32 asm sideeffect "", "={x8}"() nounwind + %4 = call i32 asm sideeffect "", "={x9}"() nounwind + %5 = call i32 asm sideeffect "", "={x28}"() nounwind + call void @standard_cc_func() + call void asm sideeffect "", "{x6},{x7},{x8},{x9},{x28}"(i32 %1, i32 %2, i32 %3, i32 %4, i32 %5) + ret void +} diff --git a/llvm/test/CodeGen/RISCV/fpclamptosat.ll b/llvm/test/CodeGen/RISCV/fpclamptosat.ll index 246e6a614d6aa..117e3e4aac45d 100644 --- a/llvm/test/CodeGen/RISCV/fpclamptosat.ll +++ b/llvm/test/CodeGen/RISCV/fpclamptosat.ll @@ -3292,30 +3292,30 @@ define i64 @ustest_f64i64_mm(double %x) { ; RV32IF-NEXT: mv a1, a0 ; RV32IF-NEXT: addi a0, sp, 8 ; RV32IF-NEXT: call __fixdfti -; RV32IF-NEXT: lw a0, 8(sp) -; RV32IF-NEXT: lw a1, 12(sp) -; RV32IF-NEXT: lw a2, 20(sp) +; RV32IF-NEXT: lw a0, 20(sp) +; RV32IF-NEXT: lw a1, 8(sp) +; RV32IF-NEXT: lw a2, 12(sp) ; RV32IF-NEXT: lw a3, 16(sp) -; RV32IF-NEXT: beqz a2, .LBB47_2 +; RV32IF-NEXT: beqz a0, .LBB47_2 ; RV32IF-NEXT: # %bb.1: # %entry -; RV32IF-NEXT: slti a4, a2, 0 +; RV32IF-NEXT: slti a4, a0, 0 ; RV32IF-NEXT: j .LBB47_3 ; RV32IF-NEXT: .LBB47_2: ; RV32IF-NEXT: seqz a4, a3 ; RV32IF-NEXT: .LBB47_3: # %entry ; RV32IF-NEXT: xori a3, a3, 1 -; RV32IF-NEXT: or a3, a3, a2 +; RV32IF-NEXT: or a3, a3, a0 ; RV32IF-NEXT: seqz a3, a3 ; RV32IF-NEXT: addi a3, a3, -1 ; RV32IF-NEXT: and a3, a3, a4 ; RV32IF-NEXT: neg a3, a3 +; RV32IF-NEXT: and a2, a3, a2 ; RV32IF-NEXT: and a1, a3, a1 ; RV32IF-NEXT: and a0, a3, a0 -; RV32IF-NEXT: and a2, a3, a2 -; RV32IF-NEXT: slti a2, a2, 0 -; RV32IF-NEXT: addi a2, a2, -1 -; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: and a1, a2, a1 +; RV32IF-NEXT: slti a0, a0, 0 +; RV32IF-NEXT: addi a3, a0, -1 +; RV32IF-NEXT: and a0, a3, a1 +; RV32IF-NEXT: and a1, a3, a2 ; RV32IF-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32IF-NEXT: .cfi_restore ra ; RV32IF-NEXT: addi sp, sp, 32 @@ -3354,30 +3354,30 @@ define i64 @ustest_f64i64_mm(double %x) { ; RV32IFD-NEXT: .cfi_offset ra, -4 ; RV32IFD-NEXT: addi a0, sp, 8 ; RV32IFD-NEXT: call __fixdfti -; RV32IFD-NEXT: lw a0, 8(sp) -; RV32IFD-NEXT: lw a1, 12(sp) -; RV32IFD-NEXT: lw a2, 20(sp) +; RV32IFD-NEXT: lw a0, 20(sp) +; RV32IFD-NEXT: lw a1, 8(sp) +; RV32IFD-NEXT: lw a2, 12(sp) ; RV32IFD-NEXT: lw a3, 16(sp) -; RV32IFD-NEXT: beqz a2, .LBB47_2 +; RV32IFD-NEXT: beqz a0, .LBB47_2 ; RV32IFD-NEXT: # %bb.1: # %entry -; RV32IFD-NEXT: slti a4, a2, 0 +; RV32IFD-NEXT: slti a4, a0, 0 ; RV32IFD-NEXT: j .LBB47_3 ; RV32IFD-NEXT: .LBB47_2: ; RV32IFD-NEXT: seqz a4, a3 ; RV32IFD-NEXT: .LBB47_3: # %entry ; RV32IFD-NEXT: xori a3, a3, 1 -; RV32IFD-NEXT: or a3, a3, a2 +; RV32IFD-NEXT: or a3, a3, a0 ; RV32IFD-NEXT: seqz a3, a3 ; RV32IFD-NEXT: addi a3, a3, -1 ; RV32IFD-NEXT: and a3, a3, a4 ; RV32IFD-NEXT: neg a3, a3 +; RV32IFD-NEXT: and a2, a3, a2 ; RV32IFD-NEXT: and a1, a3, a1 ; RV32IFD-NEXT: and a0, a3, a0 -; RV32IFD-NEXT: and a2, a3, a2 -; RV32IFD-NEXT: slti a2, a2, 0 -; RV32IFD-NEXT: addi a2, a2, -1 -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: and a1, a2, a1 +; RV32IFD-NEXT: slti a0, a0, 0 +; RV32IFD-NEXT: addi a3, a0, -1 +; RV32IFD-NEXT: and a0, a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 ; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: .cfi_restore ra ; RV32IFD-NEXT: addi sp, sp, 32 @@ -3530,30 +3530,30 @@ define i64 @ustest_f32i64_mm(float %x) { ; RV32-NEXT: .cfi_offset ra, -4 ; RV32-NEXT: addi a0, sp, 8 ; RV32-NEXT: call __fixsfti -; RV32-NEXT: lw a0, 8(sp) -; RV32-NEXT: lw a1, 12(sp) -; RV32-NEXT: lw a2, 20(sp) +; RV32-NEXT: lw a0, 20(sp) +; RV32-NEXT: lw a1, 8(sp) +; RV32-NEXT: lw a2, 12(sp) ; RV32-NEXT: lw a3, 16(sp) -; RV32-NEXT: beqz a2, .LBB50_2 +; RV32-NEXT: beqz a0, .LBB50_2 ; RV32-NEXT: # %bb.1: # %entry -; RV32-NEXT: slti a4, a2, 0 +; RV32-NEXT: slti a4, a0, 0 ; RV32-NEXT: j .LBB50_3 ; RV32-NEXT: .LBB50_2: ; RV32-NEXT: seqz a4, a3 ; RV32-NEXT: .LBB50_3: # %entry ; RV32-NEXT: xori a3, a3, 1 -; RV32-NEXT: or a3, a3, a2 +; RV32-NEXT: or a3, a3, a0 ; RV32-NEXT: seqz a3, a3 ; RV32-NEXT: addi a3, a3, -1 ; RV32-NEXT: and a3, a3, a4 ; RV32-NEXT: neg a3, a3 +; RV32-NEXT: and a2, a3, a2 ; RV32-NEXT: and a1, a3, a1 ; RV32-NEXT: and a0, a3, a0 -; RV32-NEXT: and a2, a3, a2 -; RV32-NEXT: slti a2, a2, 0 -; RV32-NEXT: addi a2, a2, -1 -; RV32-NEXT: and a0, a2, a0 -; RV32-NEXT: and a1, a2, a1 +; RV32-NEXT: slti a0, a0, 0 +; RV32-NEXT: addi a3, a0, -1 +; RV32-NEXT: and a0, a3, a1 +; RV32-NEXT: and a1, a3, a2 ; RV32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32-NEXT: .cfi_restore ra ; RV32-NEXT: addi sp, sp, 32 @@ -3767,30 +3767,30 @@ define i64 @ustest_f16i64_mm(half %x) { ; RV32-NEXT: call __extendhfsf2 ; RV32-NEXT: addi a0, sp, 8 ; RV32-NEXT: call __fixsfti -; RV32-NEXT: lw a0, 8(sp) -; RV32-NEXT: lw a1, 12(sp) -; RV32-NEXT: lw a2, 20(sp) +; RV32-NEXT: lw a0, 20(sp) +; RV32-NEXT: lw a1, 8(sp) +; RV32-NEXT: lw a2, 12(sp) ; RV32-NEXT: lw a3, 16(sp) -; RV32-NEXT: beqz a2, .LBB53_2 +; RV32-NEXT: beqz a0, .LBB53_2 ; RV32-NEXT: # %bb.1: # %entry -; RV32-NEXT: slti a4, a2, 0 +; RV32-NEXT: slti a4, a0, 0 ; RV32-NEXT: j .LBB53_3 ; RV32-NEXT: .LBB53_2: ; RV32-NEXT: seqz a4, a3 ; RV32-NEXT: .LBB53_3: # %entry ; RV32-NEXT: xori a3, a3, 1 -; RV32-NEXT: or a3, a3, a2 +; RV32-NEXT: or a3, a3, a0 ; RV32-NEXT: seqz a3, a3 ; RV32-NEXT: addi a3, a3, -1 ; RV32-NEXT: and a3, a3, a4 ; RV32-NEXT: neg a3, a3 +; RV32-NEXT: and a2, a3, a2 ; RV32-NEXT: and a1, a3, a1 ; RV32-NEXT: and a0, a3, a0 -; RV32-NEXT: and a2, a3, a2 -; RV32-NEXT: slti a2, a2, 0 -; RV32-NEXT: addi a2, a2, -1 -; RV32-NEXT: and a0, a2, a0 -; RV32-NEXT: and a1, a2, a1 +; RV32-NEXT: slti a0, a0, 0 +; RV32-NEXT: addi a3, a0, -1 +; RV32-NEXT: and a0, a3, a1 +; RV32-NEXT: and a1, a3, a2 ; RV32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32-NEXT: .cfi_restore ra ; RV32-NEXT: addi sp, sp, 32 diff --git a/llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll b/llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll index b1a6d163664e5..97d102561129d 100644 --- a/llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll +++ b/llvm/test/CodeGen/RISCV/intrinsic-cttz-elts-vscale.ll @@ -7,18 +7,18 @@ define i32 @ctz_nxv4i32( %a) #0 { ; RV32-LABEL: ctz_nxv4i32: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a0, zero, e16, m1, ta, ma -; RV32-NEXT: vid.v v10 -; RV32-NEXT: vmv.v.i v11, -1 ; RV32-NEXT: csrr a0, vlenb +; RV32-NEXT: vsetvli a1, zero, e16, m1, ta, ma +; RV32-NEXT: vid.v v10 +; RV32-NEXT: li a1, -1 ; RV32-NEXT: vsetvli zero, zero, e32, m2, ta, ma ; RV32-NEXT: vmsne.vi v0, v8, 0 ; RV32-NEXT: srli a0, a0, 1 ; RV32-NEXT: vsetvli zero, zero, e16, m1, ta, ma ; RV32-NEXT: vmv.v.x v8, a0 -; RV32-NEXT: vmacc.vv v8, v10, v11 -; RV32-NEXT: vmv.v.i v9, 0 -; RV32-NEXT: vmerge.vvm v8, v9, v8, v0 +; RV32-NEXT: vmadd.vx v10, a1, v8 +; RV32-NEXT: vmv.v.i v8, 0 +; RV32-NEXT: vmerge.vvm v8, v8, v10, v0 ; RV32-NEXT: vredmaxu.vs v8, v8, v8 ; RV32-NEXT: vmv.x.s a1, v8 ; RV32-NEXT: sub a0, a0, a1 @@ -28,18 +28,18 @@ define i32 @ctz_nxv4i32( %a) #0 { ; ; RV64-LABEL: ctz_nxv4i32: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a0, zero, e16, m1, ta, ma -; RV64-NEXT: vid.v v10 -; RV64-NEXT: vmv.v.i v11, -1 ; RV64-NEXT: csrr a0, vlenb +; RV64-NEXT: vsetvli a1, zero, e16, m1, ta, ma +; RV64-NEXT: vid.v v10 +; RV64-NEXT: li a1, -1 ; RV64-NEXT: vsetvli zero, zero, e32, m2, ta, ma ; RV64-NEXT: vmsne.vi v0, v8, 0 ; RV64-NEXT: srli a0, a0, 1 ; RV64-NEXT: vsetvli zero, zero, e16, m1, ta, ma ; RV64-NEXT: vmv.v.x v8, a0 -; RV64-NEXT: vmacc.vv v8, v10, v11 -; RV64-NEXT: vmv.v.i v9, 0 -; RV64-NEXT: vmerge.vvm v8, v9, v8, v0 +; RV64-NEXT: vmadd.vx v10, a1, v8 +; RV64-NEXT: vmv.v.i v8, 0 +; RV64-NEXT: vmerge.vvm v8, v8, v10, v0 ; RV64-NEXT: vredmaxu.vs v8, v8, v8 ; RV64-NEXT: vmv.x.s a1, v8 ; RV64-NEXT: subw a0, a0, a1 @@ -109,17 +109,17 @@ define i64 @ctz_nxv8i1_no_range( %a) { ; ; RV64-LABEL: ctz_nxv8i1_no_range: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; RV64-NEXT: vid.v v16 -; RV64-NEXT: vmv.v.i v24, -1 ; RV64-NEXT: csrr a0, vlenb +; RV64-NEXT: vsetvli a1, zero, e64, m8, ta, ma +; RV64-NEXT: vid.v v16 +; RV64-NEXT: li a1, -1 ; RV64-NEXT: vsetvli zero, zero, e16, m2, ta, ma ; RV64-NEXT: vmsne.vi v0, v8, 0 ; RV64-NEXT: vsetvli zero, zero, e64, m8, ta, ma ; RV64-NEXT: vmv.v.x v8, a0 -; RV64-NEXT: vmacc.vv v8, v16, v24 -; RV64-NEXT: vmv.v.i v16, 0 -; RV64-NEXT: vmerge.vvm v8, v16, v8, v0 +; RV64-NEXT: vmadd.vx v16, a1, v8 +; RV64-NEXT: vmv.v.i v8, 0 +; RV64-NEXT: vmerge.vvm v8, v8, v16, v0 ; RV64-NEXT: vredmaxu.vs v8, v8, v8 ; RV64-NEXT: vmv.x.s a1, v8 ; RV64-NEXT: sub a0, a0, a1 diff --git a/llvm/test/CodeGen/RISCV/machine-copyprop-noop-removal.mir b/llvm/test/CodeGen/RISCV/machine-copyprop-noop-removal.mir index d739537b50d05..293b15bf9d25e 100644 --- a/llvm/test/CodeGen/RISCV/machine-copyprop-noop-removal.mir +++ b/llvm/test/CodeGen/RISCV/machine-copyprop-noop-removal.mir @@ -1,8 +1,11 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 # RUN: llc -o - %s -mtriple=riscv64 -run-pass=machine-cp -mcp-use-is-copy-instr | FileCheck %s -## This test was added to capture a case where MachineCopyPropagation risks -## leaving a no-op register move (add, x0, reg). +## This test was added to capture a case where MachineCopyPropagation may +## leave a no-op register move (add reg, x0, reg). +## Due to the bug reported in +## , we are not currently +## able to optimize this case. --- name: ham @@ -21,6 +24,7 @@ body: | ; CHECK-NEXT: liveins: $x10 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: $x11 = ADDI $x0, 0 + ; CHECK-NEXT: renamable $x10 = ADDI killed renamable $x10, 0 ; CHECK-NEXT: BEQ renamable $x10, $x0, %bb.4 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: diff --git a/llvm/test/CodeGen/RISCV/pr148084.ll b/llvm/test/CodeGen/RISCV/pr148084.ll new file mode 100644 index 0000000000000..9fa26c74021cb --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr148084.ll @@ -0,0 +1,279 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s | FileCheck %s + +source_filename = "external/libaom/av1/encoder/tx_search.c" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-android10000" + +define fastcc void @search_tx_type() #0 { +; CHECK-LABEL: search_tx_type: +; CHECK: # %bb.0: # %._crit_edge.i +; CHECK-NEXT: # %bb.1: # %bb +; CHECK-NEXT: lbu a1, 0(zero) +; CHECK-NEXT: lw a0, 0(zero) +; CHECK-NEXT: lh a2, 0(zero) +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: srai a3, a0, 63 +; CHECK-NEXT: addi a1, a1, -1 +; CHECK-NEXT: and a1, a1, a2 +; CHECK-NEXT: andi a2, a1, 1 +; CHECK-NEXT: addi a2, a2, -1 +; CHECK-NEXT: or a3, a3, a0 +; CHECK-NEXT: or a2, a2, a3 +; CHECK-NEXT: bgez a2, .LBB0_3 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: bexti a3, a1, 1 +; CHECK-NEXT: addi a3, a3, -1 +; CHECK-NEXT: and a2, a2, a3 +; CHECK-NEXT: .LBB0_3: # %bb +; CHECK-NEXT: andi a4, a1, 4 +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: beqz a4, .LBB0_5 +; CHECK-NEXT: # %bb.4: # %bb +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: .LBB0_5: # %bb +; CHECK-NEXT: blt a2, a0, .LBB0_7 +; CHECK-NEXT: # %bb.6: # %bb +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: .LBB0_7: # %bb +; CHECK-NEXT: andi a5, a1, 8 +; CHECK-NEXT: sext.w a4, a3 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: beqz a5, .LBB0_9 +; CHECK-NEXT: # %bb.8: # %bb +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: .LBB0_9: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_11 +; CHECK-NEXT: # %bb.10: # %bb +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: .LBB0_11: # %bb +; CHECK-NEXT: andi a5, a1, 16 +; CHECK-NEXT: sext.w a4, a2 +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: beqz a5, .LBB0_13 +; CHECK-NEXT: # %bb.12: # %bb +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: .LBB0_13: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_15 +; CHECK-NEXT: # %bb.14: # %bb +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: .LBB0_15: # %bb +; CHECK-NEXT: andi a5, a1, 32 +; CHECK-NEXT: sext.w a4, a3 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: beqz a5, .LBB0_17 +; CHECK-NEXT: # %bb.16: # %bb +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: .LBB0_17: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_19 +; CHECK-NEXT: # %bb.18: # %bb +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: .LBB0_19: # %bb +; CHECK-NEXT: andi a5, a1, 64 +; CHECK-NEXT: sext.w a4, a2 +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: beqz a5, .LBB0_21 +; CHECK-NEXT: # %bb.20: # %bb +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: .LBB0_21: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_23 +; CHECK-NEXT: # %bb.22: # %bb +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: .LBB0_23: # %bb +; CHECK-NEXT: andi a5, a1, 128 +; CHECK-NEXT: sext.w a4, a3 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: beqz a5, .LBB0_25 +; CHECK-NEXT: # %bb.24: # %bb +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: .LBB0_25: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_27 +; CHECK-NEXT: # %bb.26: # %bb +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: .LBB0_27: # %bb +; CHECK-NEXT: andi a5, a1, 256 +; CHECK-NEXT: sext.w a4, a2 +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: beqz a5, .LBB0_29 +; CHECK-NEXT: # %bb.28: # %bb +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: .LBB0_29: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_31 +; CHECK-NEXT: # %bb.30: # %bb +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: .LBB0_31: # %bb +; CHECK-NEXT: andi a5, a1, 512 +; CHECK-NEXT: sext.w a4, a3 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: beqz a5, .LBB0_33 +; CHECK-NEXT: # %bb.32: # %bb +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: .LBB0_33: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_35 +; CHECK-NEXT: # %bb.34: # %bb +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: .LBB0_35: # %bb +; CHECK-NEXT: andi a5, a1, 1024 +; CHECK-NEXT: sext.w a4, a2 +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: beqz a5, .LBB0_37 +; CHECK-NEXT: # %bb.36: # %bb +; CHECK-NEXT: mv a3, a0 +; CHECK-NEXT: .LBB0_37: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_39 +; CHECK-NEXT: # %bb.38: # %bb +; CHECK-NEXT: mv a3, a2 +; CHECK-NEXT: .LBB0_39: # %bb +; CHECK-NEXT: slli a5, a1, 52 +; CHECK-NEXT: sext.w a4, a3 +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: bgez a5, .LBB0_41 +; CHECK-NEXT: # %bb.40: # %bb +; CHECK-NEXT: mv a2, a0 +; CHECK-NEXT: .LBB0_41: # %bb +; CHECK-NEXT: blt a4, a0, .LBB0_43 +; CHECK-NEXT: # %bb.42: # %bb +; CHECK-NEXT: mv a2, a3 +; CHECK-NEXT: .LBB0_43: # %bb +; CHECK-NEXT: slli a4, a1, 51 +; CHECK-NEXT: sext.w a3, a2 +; CHECK-NEXT: mv a1, a2 +; CHECK-NEXT: bltz a4, .LBB0_49 +; CHECK-NEXT: # %bb.44: # %bb +; CHECK-NEXT: bge a3, a0, .LBB0_50 +; CHECK-NEXT: .LBB0_45: # %bb +; CHECK-NEXT: sext.w a2, a1 +; CHECK-NEXT: blt a2, a0, .LBB0_47 +; CHECK-NEXT: .LBB0_46: # %bb +; CHECK-NEXT: mv a0, a1 +; CHECK-NEXT: .LBB0_47: # %bb +; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: # %bb.48: # %get_tx_mask.exit +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_49: # %bb +; CHECK-NEXT: mv a1, a0 +; CHECK-NEXT: blt a3, a0, .LBB0_45 +; CHECK-NEXT: .LBB0_50: # %bb +; CHECK-NEXT: mv a1, a2 +; CHECK-NEXT: sext.w a2, a2 +; CHECK-NEXT: bge a2, a0, .LBB0_46 +; CHECK-NEXT: j .LBB0_47 +._crit_edge.i: + %.in196.i = load i16, ptr null, align 2 + %i2 = load i16, ptr null, align 2 + %i3 = and i16 %i2, %.in196.i + %i9 = trunc nuw i8 0 to i1 + br i1 %i9, label %get_tx_mask.exit, label %bb + +bb: ; preds = %._crit_edge.i + %i13 = load i8, ptr null, align 1 + %i14 = icmp eq i8 %i13, 0 + %spec.select211.i = select i1 %i14, i16 0, i16 %i3 + %i19 = load i32, ptr null, align 4 + %i20 = zext i16 %spec.select211.i to i32 + %i21 = load i32, ptr null, align 4 + %i22 = icmp sgt i32 %i21, -1 + %i23 = and i32 %i20, 1 + %.not203.i = icmp eq i32 %i23, 0 + %spec.select212.i = select i1 %.not203.i, i32 -1, i32 %i21 + %.1174.i = select i1 %i22, i32 %spec.select212.i, i32 -1 + %i28 = icmp sgt i32 0, %.1174.i + %i29 = and i32 %i20, 2 + %.not203.1.not.i = icmp eq i32 %i29, 0 + %spec.select212.1.i = select i1 %.not203.1.not.i, i32 %.1174.i, i32 0 + %.1174.1.i = select i1 %i28, i32 %spec.select212.1.i, i32 %.1174.i + %i30 = load i32, ptr null, align 4 + %i31 = icmp sgt i32 %i30, %.1174.1.i + %i32 = and i32 %i20, 4 + %.not203.2.i = icmp eq i32 %i32, 0 + %spec.select212.2.i = select i1 %.not203.2.i, i32 %.1174.1.i, i32 %i30 + %.1174.2.i = select i1 %i31, i32 %spec.select212.2.i, i32 %.1174.1.i + %i36 = load i32, ptr null, align 4 + %i37 = icmp sgt i32 %i36, %.1174.2.i + %i38 = and i32 %i20, 8 + %.not203.3.i = icmp eq i32 %i38, 0 + %spec.select212.3.i = select i1 %.not203.3.i, i32 %.1174.2.i, i32 %i36 + %.1174.3.i = select i1 %i37, i32 %spec.select212.3.i, i32 %.1174.2.i + %i42 = load i32, ptr null, align 4 + %i43 = icmp sgt i32 %i42, %.1174.3.i + %i44 = and i32 %i20, 16 + %.not203.4.i = icmp eq i32 %i44, 0 + %spec.select212.4.i = select i1 %.not203.4.i, i32 %.1174.3.i, i32 %i42 + %.1174.4.i = select i1 %i43, i32 %spec.select212.4.i, i32 %.1174.3.i + %i48 = load i32, ptr null, align 4 + %i49 = icmp sgt i32 %i48, %.1174.4.i + %i50 = and i32 %i20, 32 + %.not203.5.i = icmp eq i32 %i50, 0 + %spec.select212.5.i = select i1 %.not203.5.i, i32 %.1174.4.i, i32 %i48 + %.1174.5.i = select i1 %i49, i32 %spec.select212.5.i, i32 %.1174.4.i + %i51 = load i32, ptr null, align 4 + %i52 = icmp sgt i32 %i51, %.1174.5.i + %i53 = and i32 %i20, 64 + %.not203.6.i = icmp eq i32 %i53, 0 + %spec.select212.6.i = select i1 %.not203.6.i, i32 %.1174.5.i, i32 %i51 + %.1174.6.i = select i1 %i52, i32 %spec.select212.6.i, i32 %.1174.5.i + %i56 = load i32, ptr null, align 4 + %i57 = icmp sgt i32 %i56, %.1174.6.i + %i58 = and i32 %i20, 128 + %.not203.7.i = icmp eq i32 %i58, 0 + %spec.select212.7.i = select i1 %.not203.7.i, i32 %.1174.6.i, i32 %i56 + %.1174.7.i = select i1 %i57, i32 %spec.select212.7.i, i32 %.1174.6.i + %i60 = load i32, ptr null, align 4 + %i61 = icmp sgt i32 %i60, %.1174.7.i + %i62 = and i32 %i20, 256 + %.not203.8.i = icmp eq i32 %i62, 0 + %spec.select212.8.i = select i1 %.not203.8.i, i32 %.1174.7.i, i32 %i60 + %.1174.8.i = select i1 %i61, i32 %spec.select212.8.i, i32 %.1174.7.i + %i63 = load i32, ptr null, align 4 + %i64 = icmp sgt i32 %i63, %.1174.8.i + %i65 = and i32 %i20, 512 + %.not203.9.i = icmp eq i32 %i65, 0 + %spec.select212.9.i = select i1 %.not203.9.i, i32 %.1174.8.i, i32 %i63 + %.1174.9.i = select i1 %i64, i32 %spec.select212.9.i, i32 %.1174.8.i + %i67 = load i32, ptr null, align 4 + %i68 = icmp sgt i32 %i67, %.1174.9.i + %i69 = and i32 %i20, 1024 + %.not203.10.i = icmp eq i32 %i69, 0 + %spec.select212.10.i = select i1 %.not203.10.i, i32 %.1174.9.i, i32 %i67 + %.1174.10.i = select i1 %i68, i32 %spec.select212.10.i, i32 %.1174.9.i + %i70 = load i32, ptr null, align 4 + %i71 = icmp sgt i32 %i70, %.1174.10.i + %i72 = and i32 %i20, 2048 + %.not203.11.i = icmp eq i32 %i72, 0 + %spec.select212.11.i = select i1 %.not203.11.i, i32 %.1174.10.i, i32 %i70 + %.1174.11.i = select i1 %i71, i32 %spec.select212.11.i, i32 %.1174.10.i + %i75 = load i32, ptr null, align 4 + %i76 = icmp sgt i32 %i75, %.1174.11.i + %i77 = and i32 %i20, 4096 + %.not203.12.i = icmp eq i32 %i77, 0 + %spec.select212.12.i = select i1 %.not203.12.i, i32 %.1174.11.i, i32 %i75 + %.1174.12.i = select i1 %i76, i32 %spec.select212.12.i, i32 %.1174.11.i + %i80 = load i32, ptr null, align 4 + %i81 = icmp sgt i32 %i80, %.1174.12.i + %spec.select212.13.i = select i1 false, i32 %.1174.12.i, i32 %i80 + %.1174.13.i = select i1 %i81, i32 %spec.select212.13.i, i32 %.1174.12.i + %.1172.13.i = select i1 %i81, i32 13, i32 0 + %i84 = icmp sgt i32 0, %.1174.13.i + %.1172.14.i = select i1 %i84, i32 14, i32 %.1172.13.i + %i88 = icmp slt i32 0, %i19 + %i89 = select i1 %i88, i16 -32768, i16 0 + %i90 = zext i16 %i89 to i32 + %i91 = shl nuw nsw i32 1, %.1172.14.i + %i92 = and i32 %i91, %i90 + %.not200.i = icmp eq i32 %i92, 0 + %i93 = trunc nuw i32 %i91 to i16 + %i94 = xor i16 %i93, -1 + %i95 = select i1 %.not200.i, i16 -1, i16 %i94 + %.2177.i = and i16 %i95, %i89 + %i96 = xor i16 %.2177.i, -1 + %i97 = and i16 %spec.select211.i, %i96 + br label %get_tx_mask.exit + +get_tx_mask.exit: ; preds = %._crit_edge.i, %bb + %.1261.i = phi i16 [ %i97, %bb ], [ 0, %._crit_edge.i ] + %i99 = icmp eq i16 %.1261.i, 0 + %.2262.i = select i1 %i99, i16 0, i16 %.1261.i + ret void +} + +attributes #0 = { noimplicitfloat nounwind sspstrong uwtable vscale_range(2,1024) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic-rv64" "target-features"="+64bit,+a,+b,+c,+d,+f,+m,+relax,+unaligned-scalar-mem,+unaligned-vector-mem,+v,+zaamo,+zalrsc,+zba,+zbb,+zbs,+zca,+zcd,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-e,-experimental-p,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqccmp,-experimental-xqcia,-experimental-xqciac,-experimental-xqcibi,-experimental-xqcibm,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqciio,-experimental-xqcilb,-experimental-xqcili,-experimental-xqcilia,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisim,-experimental-xqcisls,-experimental-xqcisync,-experimental-xrivosvisni,-experimental-xrivosvizip,-experimental-xsfmclic,-experimental-xsfsclic,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-experimental-zvqdotq,-h,-q,-sdext,-sdtrig,-sha,-shcounterenw,-shgatpa,-shlcofideleg,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcntrpmf,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-xandesperf,-xandesvbfhcvt,-xandesvdot,-xandesvpackfph,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xmipscmov,-xmipslsp,-xsfcease,-xsfmm128t,-xsfmm16t,-xsfmm32a16f,-xsfmm32a32f,-xsfmm32a8f,-xsfmm32a8i,-xsfmm32t,-xsfmm64a64f,-xsfmm64t,-xsfmmbase,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zabha,-zacas,-zama16b,-zawrs,-zbc,-zbkb,-zbkc,-zbkx,-zcb,-zce,-zcf,-zclsd,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccamoc,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zilsd,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" } diff --git a/llvm/test/CodeGen/RISCV/pr153598.mir b/llvm/test/CodeGen/RISCV/pr153598.mir new file mode 100644 index 0000000000000..a084197fe83cc --- /dev/null +++ b/llvm/test/CodeGen/RISCV/pr153598.mir @@ -0,0 +1,23 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=riscv32 -mattr=+zcmp -run-pass=riscv-move-merge -verify-machineinstrs %s -o - | FileCheck %s +--- +name: mov-merge +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x8, $x9 + ; CHECK-LABEL: name: mov-merge + ; CHECK: liveins: $x8, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x12 = ADDI $x0, -3 + ; CHECK-NEXT: SW renamable $x9, $x2, 56 + ; CHECK-NEXT: CM_MVA01S killed renamable $x9, renamable $x8, implicit-def $x10, implicit-def $x11 + ; CHECK-NEXT: SW renamable $x8, $x2, 60 + ; CHECK-NEXT: PseudoRET + $x12 = ADDI $x0, -3 + SW renamable $x9, $x2, 56 + $x10 = ADDI killed renamable $x9, 0 + SW renamable $x8, $x2, 60 + $x11 = ADDI killed renamable $x8, 0 + PseudoRET +... diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vw-web-simplification.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vw-web-simplification.ll index 227a428831b60..ea4add2da5ebc 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vw-web-simplification.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vw-web-simplification.ll @@ -58,3 +58,26 @@ define <2 x i16> @vwmul_v2i16_multiple_users(ptr %x, ptr %y, ptr %z) { %i = or <2 x i16> %h, %g ret <2 x i16> %i } + +; Make sure we have a vsext.vl and a vwaddu.vx. +define <4 x i32> @pr159152(<4 x i8> %x) { +; NO_FOLDING-LABEL: pr159152: +; NO_FOLDING: # %bb.0: +; NO_FOLDING-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; NO_FOLDING-NEXT: vsext.vf2 v9, v8 +; NO_FOLDING-NEXT: li a0, 9 +; NO_FOLDING-NEXT: vwaddu.vx v8, v9, a0 +; NO_FOLDING-NEXT: ret +; +; FOLDING-LABEL: pr159152: +; FOLDING: # %bb.0: +; FOLDING-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; FOLDING-NEXT: vsext.vf2 v9, v8 +; FOLDING-NEXT: li a0, 9 +; FOLDING-NEXT: vwaddu.vx v8, v9, a0 +; FOLDING-NEXT: ret + %a = sext <4 x i8> %x to <4 x i16> + %b = zext <4 x i16> %a to <4 x i32> + %c = add <4 x i32> %b, + ret <4 x i32> %c +} diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-to-vmv.mir b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-to-vmv.mir index a050034c63168..a7eaf39793236 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-to-vmv.mir +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-to-vmv.mir @@ -78,12 +78,12 @@ body: | ; CHECK-NEXT: %false:vrnov0 = COPY $v9 ; CHECK-NEXT: %mask:vmv0 = COPY $v0 ; CHECK-NEXT: %true:vrnov0 = PseudoVADD_VV_M1_MASK %false, $noreg, $noreg, %mask, 4, 5 /* e32 */, 0 /* tu, mu */ - ; CHECK-NEXT: %x:vr = PseudoVMV_V_V_M1 %pt, %true, 8, 5 /* e32 */, 0 /* tu, mu */ + ; CHECK-NEXT: %x:vr = PseudoVMV_V_V_M1 %pt, %true, 4, 5 /* e32 */, 0 /* tu, mu */ %pt:vrnov0 = COPY $v8 %false:vrnov0 = COPY $v9 %mask:vmv0 = COPY $v0 - %true:vrnov0 = PseudoVADD_VV_M1_MASK %false, $noreg, $noreg, %mask, 4, 5 /* e32 */, 0 /* tu, mu */ - %x:vrnov0 = PseudoVMERGE_VVM_M1 %pt, %false, %true, %mask, 8, 5 /* e32 */ + %true:vrnov0 = PseudoVADD_VV_M1_MASK %false, $noreg, $noreg, %mask, 8, 5 /* e32 */, 0 /* tu, mu */ + %x:vrnov0 = PseudoVMERGE_VVM_M1 %pt, %false, %true, %mask, 4, 5 /* e32 */ ... --- # Shouldn't be converted because false operands are different @@ -163,3 +163,47 @@ body: | %true:vrnov0 = PseudoVADD_VV_M1_MASK $noreg, $noreg, $noreg, %mask, 4, 5 /* e32 */, 0 /* tu, mu */ bb.1: %5:vrnov0 = PseudoVMERGE_VVM_M1 $noreg, %false, %true, %mask, 4, 5 /* e32 */ +... +--- +# Shouldn't be converted because vmerge adds back in elements from false past avl that would be lost if we converted to vmv.v.v +name: preserve_false +body: | + bb.0: + liveins: $v8, $v9, $v0, $x8, $x9 + ; CHECK-LABEL: name: preserve_false + ; CHECK: liveins: $v8, $v9, $v0, $x8, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %pt:vrnov0 = COPY $v8 + ; CHECK-NEXT: %false:vr = COPY $v9 + ; CHECK-NEXT: %mask:vmv0 = COPY $v0 + ; CHECK-NEXT: %avl1:gprnox0 = COPY $x8 + ; CHECK-NEXT: %avl2:gprnox0 = COPY $x9 + ; CHECK-NEXT: %true:vrnov0 = PseudoVADD_VV_M1_MASK $noreg, $noreg, $noreg, %mask, %avl1, 5 /* e32 */, 3 /* ta, ma */ + ; CHECK-NEXT: [[PseudoVMERGE_VVM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_M1 %pt, %false, %true, %mask, %avl2, 5 /* e32 */ + %pt:vrnov0 = COPY $v8 + %false:vr = COPY $v9 + %mask:vmv0 = COPY $v0 + %avl1:gprnox0 = COPY $x8 + %avl2:gprnox0 = COPY $x9 + %true:vrnov0 = PseudoVADD_VV_M1_MASK $noreg, $noreg, $noreg, %mask, %avl1, 5 /* e32 */, 3 /* ta, ma */ + %5:vrnov0 = PseudoVMERGE_VVM_M1 %pt, %false, %true, %mask, %avl2, 5 /* e32 */ +... +--- +# But we can convert this one because vmerge's avl being <= true's means we don't lose any false elements past avl. +name: preserve_false_avl_known_le +body: | + bb.0: + liveins: $v8, $v9, $v0 + ; CHECK-LABEL: name: preserve_false_avl_known_le + ; CHECK: liveins: $v8, $v9, $v0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %pt:vr = COPY $v8 + ; CHECK-NEXT: %false:vrnov0 = COPY $v9 + ; CHECK-NEXT: %mask:vmv0 = COPY $v0 + ; CHECK-NEXT: %true:vrnov0 = PseudoVADD_VV_M1_MASK %false, $noreg, $noreg, %mask, 1, 5 /* e32 */, 3 /* ta, ma */ + ; CHECK-NEXT: [[PseudoVMV_V_V_M1_:%[0-9]+]]:vr = PseudoVMV_V_V_M1 %pt, %true, 1, 5 /* e32 */, 0 /* tu, mu */ + %pt:vrnov0 = COPY $v8 + %false:vr = COPY $v9 + %mask:vmv0 = COPY $v0 + %true:vrnov0 = PseudoVADD_VV_M1_MASK $noreg, $noreg, $noreg, %mask, 2, 5 /* e32 */, 3 /* ta, ma */ + %5:vrnov0 = PseudoVMERGE_VVM_M1 %pt, %false, %true, %mask, 1, 5 /* e32 */ diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-vmerge-to-vmv.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-vmerge-to-vmv.ll index 3aeb4e864627c..9ffc84a8a0e4a 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-vmerge-to-vmv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-vmerge-to-vmv.ll @@ -71,10 +71,31 @@ define @vpmerge_m8( %x, ret %1 } -declare @llvm.vp.merge.nxv1i8(, , , i32) -declare @llvm.vp.merge.nxv2i8(, , , i32) -declare @llvm.vp.merge.nxv4i8(, , , i32) -declare @llvm.vp.merge.nxv8i8(, , , i32) -declare @llvm.vp.merge.nxv8i16(, , , i32) -declare @llvm.vp.merge.nxv8i32(, , , i32) -declare @llvm.vp.merge.nxv8i64(, , , i32) +; Shouldn't be converted because vmerge adds back in elements from false past avl that would be lost if we converted to vmv.v.v +define @preserve_false(ptr %p, %pt, %false, %mask, i64 %avl1, i64 %avl2) { +; CHECK-LABEL: preserve_false: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; CHECK-NEXT: vmv1r.v v10, v9 +; CHECK-NEXT: vle32.v v10, (a0), v0.t +; CHECK-NEXT: vsetvli zero, a2, e32, m1, tu, ma +; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 +; CHECK-NEXT: ret + %true = call @llvm.riscv.vle.mask( %false, ptr %p, %mask, i64 %avl1, i64 3) + %res = call @llvm.riscv.vmerge( %pt, %false, %true, %mask, i64 %avl2) + ret %res +} + +; Can fold this because its avl is known to be <= than true, so no elements from false need to be introduced past avl. +define @preserve_false_avl_known_le(ptr %p, %pt, %false, %mask) { +; CHECK-LABEL: preserve_false_avl_known_le: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma +; CHECK-NEXT: vle32.v v9, (a0), v0.t +; CHECK-NEXT: vsetvli zero, zero, e32, m1, tu, ma +; CHECK-NEXT: vmv.v.v v8, v9 +; CHECK-NEXT: ret + %true = call @llvm.riscv.vle.mask( %false, ptr %p, %mask, i64 2, i64 3) + %res = call @llvm.riscv.vmerge( %pt, %false, %true, %mask, i64 1) + ret %res +} diff --git a/llvm/test/CodeGen/RISCV/rvv/stack-probing-dynamic.ll b/llvm/test/CodeGen/RISCV/rvv/stack-probing-dynamic.ll index d666832cf6e0b..c79fb0f91b21f 100644 --- a/llvm/test/CodeGen/RISCV/rvv/stack-probing-dynamic.ll +++ b/llvm/test/CodeGen/RISCV/rvv/stack-probing-dynamic.ll @@ -460,9 +460,9 @@ define void @reserved_call_frame(i64 %n) #0 { ; RV64I-NEXT: lui a0, 1 ; RV64I-NEXT: sub sp, sp, a0 ; RV64I-NEXT: sd zero, 0(sp) -; RV64I-NEXT: .cfi_def_cfa_offset 4096 +; RV64I-NEXT: .cfi_def_cfa_offset 6128 ; RV64I-NEXT: addi sp, sp, -48 -; RV64I-NEXT: .cfi_def_cfa_offset 4144 +; RV64I-NEXT: .cfi_def_cfa_offset 6176 ; RV64I-NEXT: lui a0, 1 ; RV64I-NEXT: add a0, sp, a0 ; RV64I-NEXT: call callee_stack_args @@ -485,9 +485,9 @@ define void @reserved_call_frame(i64 %n) #0 { ; RV32I-NEXT: lui a0, 1 ; RV32I-NEXT: sub sp, sp, a0 ; RV32I-NEXT: sw zero, 0(sp) -; RV32I-NEXT: .cfi_def_cfa_offset 4096 +; RV32I-NEXT: .cfi_def_cfa_offset 6128 ; RV32I-NEXT: addi sp, sp, -80 -; RV32I-NEXT: .cfi_def_cfa_offset 4176 +; RV32I-NEXT: .cfi_def_cfa_offset 6208 ; RV32I-NEXT: lui a0, 1 ; RV32I-NEXT: addi a0, a0, 36 ; RV32I-NEXT: add a0, sp, a0 diff --git a/llvm/test/CodeGen/RISCV/rvv/vsha2cl.ll b/llvm/test/CodeGen/RISCV/rvv/vsha2cl.ll index f29c74ae69bf6..697c582dcb38b 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vsha2cl.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vsha2cl.ll @@ -21,7 +21,7 @@ define @intrinsic_vsha2cl_vv_nxv4i32_nxv4i32( @llvm.riscv.vsha2cl.nxv4i32.nxv4i32( @@ -45,7 +45,7 @@ define @intrinsic_vsha2cl_vv_nxv8i32_nxv8i32( @llvm.riscv.vsha2cl.nxv8i32.nxv8i32( @@ -70,7 +70,7 @@ define @intrinsic_vsha2cl_vv_nxv16i32_nxv16i32( @llvm.riscv.vsha2cl.nxv16i32.nxv16i32( @@ -94,7 +94,7 @@ define @intrinsic_vsha2cl_vv_nxv4i64_nxv4i64( @llvm.riscv.vsha2cl.nxv4i64.nxv4i64( @@ -119,7 +119,7 @@ define @intrinsic_vsha2cl_vv_nxv8i64_nxv8i64( @llvm.riscv.vsha2cl.nxv8i64.nxv8i64( diff --git a/llvm/test/CodeGen/RISCV/sextw-removal.ll b/llvm/test/CodeGen/RISCV/sextw-removal.ll index b128abb6b5bdd..12d59f1f26902 100644 --- a/llvm/test/CodeGen/RISCV/sextw-removal.ll +++ b/llvm/test/CodeGen/RISCV/sextw-removal.ll @@ -1352,6 +1352,7 @@ define signext i32 @sextw_sh2add(i1 zeroext %0, ptr %1, i32 signext %2, i32 sign ; NOREMOVAL-LABEL: sextw_sh2add: ; NOREMOVAL: # %bb.0: ; NOREMOVAL-NEXT: sh2add a2, a2, a3 +; NOREMOVAL-NEXT: mv a2, a2 ; NOREMOVAL-NEXT: beqz a0, .LBB22_2 ; NOREMOVAL-NEXT: # %bb.1: ; NOREMOVAL-NEXT: sw a2, 0(a1) diff --git a/llvm/test/CodeGen/RISCV/stack-probing-frame-setup.mir b/llvm/test/CodeGen/RISCV/stack-probing-frame-setup.mir new file mode 100644 index 0000000000000..9ab7f41045c4d --- /dev/null +++ b/llvm/test/CodeGen/RISCV/stack-probing-frame-setup.mir @@ -0,0 +1,198 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=riscv64 -x mir -run-pass=prologepilog -verify-machineinstrs < %s \ +# RUN: | FileCheck %s -check-prefixes=RV64I +# RUN: llc -mtriple=riscv32 -x mir -run-pass=prologepilog -verify-machineinstrs < %s \ +# RUN: | FileCheck %s -check-prefixes=RV32I +--- | + ; Function Attrs: uwtable + define void @no_reserved_call_frame(i64 %n) #0 { + entry: + %v = alloca i32, i64 %n, align 4 + call void @callee_stack_args(ptr %v, [518 x i64] poison) + ret void + } + + declare void @callee_stack_args(ptr, [518 x i64]) #1 + + attributes #0 = { uwtable "frame-pointer"="none" "probe-stack"="inline-asm" "target-features"="+m" } + attributes #1 = { "target-features"="+m" } +... +--- +name: no_reserved_call_frame +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +noPhis: true +isSSA: false +noVRegs: true +hasFakeUses: false +callsEHReturn: false +callsUnwindInit: false +hasEHContTarget: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: true +registers: [] +liveins: + - { reg: '$x10', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 8 + adjustsStack: true + hasCalls: true + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: v, type: variable-sized, offset: 0, alignment: 1, stack-id: default, + callee-saved-register: '', callee-saved-restored: true, local-offset: 0, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + varArgsFrameIndex: 0 + varArgsSaveSize: 0 +body: | + ; RV64I-LABEL: name: no_reserved_call_frame + ; RV64I: bb.0.entry: + ; RV64I-NEXT: successors: %bb.1(0x80000000) + ; RV64I-NEXT: liveins: $x10, $x1 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: $x2 = frame-setup ADDI $x2, -16 + ; RV64I-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; RV64I-NEXT: frame-setup SD killed $x1, $x2, 8 :: (store (s64) into %stack.1) + ; RV64I-NEXT: frame-setup SD killed $x8, $x2, 0 :: (store (s64) into %stack.2) + ; RV64I-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 + ; RV64I-NEXT: frame-setup CFI_INSTRUCTION offset $x8, -16 + ; RV64I-NEXT: $x8 = frame-setup ADDI $x2, 16 + ; RV64I-NEXT: frame-setup CFI_INSTRUCTION def_cfa $x8, 0 + ; RV64I-NEXT: renamable $x10 = SLLI killed renamable $x10, 2 + ; RV64I-NEXT: renamable $x10 = nuw ADDI killed renamable $x10, 15 + ; RV64I-NEXT: renamable $x10 = ANDI killed renamable $x10, -16 + ; RV64I-NEXT: renamable $x10 = SUB $x2, killed renamable $x10 + ; RV64I-NEXT: renamable $x11 = LUI 1 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: bb.1.entry: + ; RV64I-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: $x2 = SUB $x2, renamable $x11 + ; RV64I-NEXT: SD $x0, $x2, 0 + ; RV64I-NEXT: BLT renamable $x10, $x2, %bb.1 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: bb.2.entry: + ; RV64I-NEXT: liveins: $x10 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: $x2 = ADDI renamable $x10, 0 + ; RV64I-NEXT: $x11 = LUI 1 + ; RV64I-NEXT: $x2 = SUB $x2, killed $x11 + ; RV64I-NEXT: PseudoCALL target-flags(riscv-call) @callee_stack_args, csr_ilp32_lp64, implicit-def dead $x1, implicit $x10, implicit undef $x11, implicit undef $x12, implicit undef $x13, implicit undef $x14, implicit undef $x15, implicit undef $x16, implicit undef $x17, implicit-def $x2 + ; RV64I-NEXT: $x10 = LUI 1 + ; RV64I-NEXT: $x2 = ADD $x2, killed $x10 + ; RV64I-NEXT: $x2 = frame-destroy ADDI $x8, -16 + ; RV64I-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $x2, 16 + ; RV64I-NEXT: $x1 = frame-destroy LD $x2, 8 :: (load (s64) from %stack.1) + ; RV64I-NEXT: $x8 = frame-destroy LD $x2, 0 :: (load (s64) from %stack.2) + ; RV64I-NEXT: frame-destroy CFI_INSTRUCTION restore $x1 + ; RV64I-NEXT: frame-destroy CFI_INSTRUCTION restore $x8 + ; RV64I-NEXT: $x2 = frame-destroy ADDI $x2, 16 + ; RV64I-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; RV64I-NEXT: PseudoRET + ; + ; RV32I-LABEL: name: no_reserved_call_frame + ; RV32I: bb.0.entry: + ; RV32I-NEXT: successors: %bb.1(0x80000000) + ; RV32I-NEXT: liveins: $x10, $x1 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: $x2 = frame-setup ADDI $x2, -16 + ; RV32I-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; RV32I-NEXT: frame-setup SW killed $x1, $x2, 12 :: (store (s32) into %stack.1) + ; RV32I-NEXT: frame-setup SW killed $x8, $x2, 8 :: (store (s32) into %stack.2) + ; RV32I-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -4 + ; RV32I-NEXT: frame-setup CFI_INSTRUCTION offset $x8, -8 + ; RV32I-NEXT: $x8 = frame-setup ADDI $x2, 16 + ; RV32I-NEXT: frame-setup CFI_INSTRUCTION def_cfa $x8, 0 + ; RV32I-NEXT: renamable $x10 = SLLI killed renamable $x10, 2 + ; RV32I-NEXT: renamable $x10 = nuw ADDI killed renamable $x10, 15 + ; RV32I-NEXT: renamable $x10 = ANDI killed renamable $x10, -16 + ; RV32I-NEXT: renamable $x10 = SUB $x2, killed renamable $x10 + ; RV32I-NEXT: renamable $x11 = LUI 1 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: bb.1.entry: + ; RV32I-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: $x2 = SUB $x2, renamable $x11 + ; RV32I-NEXT: SD $x0, $x2, 0 + ; RV32I-NEXT: BLT renamable $x10, $x2, %bb.1 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: bb.2.entry: + ; RV32I-NEXT: liveins: $x10 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: $x2 = ADDI renamable $x10, 0 + ; RV32I-NEXT: $x11 = LUI 1 + ; RV32I-NEXT: $x2 = SUB $x2, killed $x11 + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_stack_args, csr_ilp32_lp64, implicit-def dead $x1, implicit $x10, implicit undef $x11, implicit undef $x12, implicit undef $x13, implicit undef $x14, implicit undef $x15, implicit undef $x16, implicit undef $x17, implicit-def $x2 + ; RV32I-NEXT: $x10 = LUI 1 + ; RV32I-NEXT: $x2 = ADD $x2, killed $x10 + ; RV32I-NEXT: $x2 = frame-destroy ADDI $x8, -16 + ; RV32I-NEXT: frame-destroy CFI_INSTRUCTION def_cfa $x2, 16 + ; RV32I-NEXT: $x1 = frame-destroy LW $x2, 12 :: (load (s32) from %stack.1) + ; RV32I-NEXT: $x8 = frame-destroy LW $x2, 8 :: (load (s32) from %stack.2) + ; RV32I-NEXT: frame-destroy CFI_INSTRUCTION restore $x1 + ; RV32I-NEXT: frame-destroy CFI_INSTRUCTION restore $x8 + ; RV32I-NEXT: $x2 = frame-destroy ADDI $x2, 16 + ; RV32I-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0 + ; RV32I-NEXT: PseudoRET + bb.0.entry: + successors: %bb.1(0x80000000) + liveins: $x10 + + renamable $x10 = SLLI killed renamable $x10, 2 + renamable $x10 = nuw ADDI killed renamable $x10, 15 + renamable $x10 = ANDI killed renamable $x10, -16 + renamable $x10 = SUB $x2, killed renamable $x10 + renamable $x11 = LUI 1 + + bb.1.entry: + successors: %bb.2(0x40000000), %bb.1(0x40000000) + liveins: $x10, $x11 + + $x2 = SUB $x2, renamable $x11 + SD $x0, $x2, 0 + BLT renamable $x10, $x2, %bb.1 + + bb.2.entry: + liveins: $x10 + + $x2 = ADDI renamable $x10, 0 + ADJCALLSTACKDOWN 4088, 0, implicit-def dead $x2, implicit $x2 + PseudoCALL target-flags(riscv-call) @callee_stack_args, csr_ilp32_lp64, implicit-def dead $x1, implicit $x10, implicit undef $x11, implicit undef $x12, implicit undef $x13, implicit undef $x14, implicit undef $x15, implicit undef $x16, implicit undef $x17, implicit-def $x2 + ADJCALLSTACKUP 4088, 0, implicit-def dead $x2, implicit $x2 + PseudoRET +... diff --git a/llvm/test/CodeGen/RISCV/wide-scalar-shift-legalization.ll b/llvm/test/CodeGen/RISCV/wide-scalar-shift-legalization.ll index 32753ca382fc7..cd7f30d8f5898 100644 --- a/llvm/test/CodeGen/RISCV/wide-scalar-shift-legalization.ll +++ b/llvm/test/CodeGen/RISCV/wide-scalar-shift-legalization.ll @@ -716,92 +716,101 @@ define void @lshr_16bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: slli a4, a4, 8 ; RV32I-NEXT: slli a5, a5, 16 ; RV32I-NEXT: slli a6, a6, 24 +; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: or a4, a6, a5 +; RV32I-NEXT: lbu a5, 8(a0) +; RV32I-NEXT: lbu a6, 9(a0) +; RV32I-NEXT: lbu t3, 10(a0) +; RV32I-NEXT: lbu t4, 11(a0) ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: or a4, a4, a3 -; RV32I-NEXT: or a5, a6, a5 -; RV32I-NEXT: or a3, t0, a7 -; RV32I-NEXT: lbu a6, 8(a0) -; RV32I-NEXT: lbu a7, 9(a0) -; RV32I-NEXT: lbu t0, 10(a0) -; RV32I-NEXT: lbu t3, 11(a0) ; RV32I-NEXT: slli t1, t1, 16 ; RV32I-NEXT: slli t2, t2, 24 -; RV32I-NEXT: slli a7, a7, 8 -; RV32I-NEXT: slli t0, t0, 16 -; RV32I-NEXT: slli t3, t3, 24 -; RV32I-NEXT: or t1, t2, t1 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a7, t3, t0 -; RV32I-NEXT: lbu t0, 12(a0) -; RV32I-NEXT: lbu t2, 13(a0) -; RV32I-NEXT: lbu t3, 14(a0) -; RV32I-NEXT: lbu t4, 15(a0) -; RV32I-NEXT: lbu a0, 0(a1) +; RV32I-NEXT: slli a6, a6, 8 +; RV32I-NEXT: or a7, t0, a7 +; RV32I-NEXT: or t0, t2, t1 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: lbu a6, 12(a0) +; RV32I-NEXT: lbu t1, 13(a0) +; RV32I-NEXT: lbu t2, 14(a0) +; RV32I-NEXT: lbu a0, 15(a0) +; RV32I-NEXT: slli t3, t3, 16 +; RV32I-NEXT: slli t4, t4, 24 +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: slli t2, t2, 16 +; RV32I-NEXT: slli a0, a0, 24 +; RV32I-NEXT: or t3, t4, t3 +; RV32I-NEXT: or a6, t1, a6 +; RV32I-NEXT: or a0, a0, t2 +; RV32I-NEXT: lbu t1, 1(a1) +; RV32I-NEXT: lbu t2, 0(a1) +; RV32I-NEXT: lbu t4, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: or t1, t1, t2 ; RV32I-NEXT: sw zero, 16(sp) ; RV32I-NEXT: sw zero, 20(sp) ; RV32I-NEXT: sw zero, 24(sp) ; RV32I-NEXT: sw zero, 28(sp) -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: or a1, t2, t0 -; RV32I-NEXT: mv t0, sp -; RV32I-NEXT: slli t3, t3, 16 -; RV32I-NEXT: slli t4, t4, 24 -; RV32I-NEXT: or t2, t4, t3 -; RV32I-NEXT: srli t3, a0, 3 -; RV32I-NEXT: or a4, a5, a4 -; RV32I-NEXT: andi a5, a0, 31 -; RV32I-NEXT: andi t3, t3, 12 -; RV32I-NEXT: xori a5, a5, 31 -; RV32I-NEXT: or a3, t1, a3 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a1, t2, a1 -; RV32I-NEXT: add t0, t0, t3 -; RV32I-NEXT: sw a4, 0(sp) -; RV32I-NEXT: sw a3, 4(sp) -; RV32I-NEXT: sw a6, 8(sp) -; RV32I-NEXT: sw a1, 12(sp) -; RV32I-NEXT: lw a1, 4(t0) -; RV32I-NEXT: lw a3, 8(t0) -; RV32I-NEXT: lw a4, 0(t0) -; RV32I-NEXT: lw a6, 12(t0) -; RV32I-NEXT: srl a7, a1, a0 -; RV32I-NEXT: slli t0, a3, 1 -; RV32I-NEXT: srl a4, a4, a0 -; RV32I-NEXT: slli a1, a1, 1 -; RV32I-NEXT: srl a3, a3, a0 -; RV32I-NEXT: slli t1, a6, 1 -; RV32I-NEXT: srl a0, a6, a0 -; RV32I-NEXT: sll a6, t0, a5 -; RV32I-NEXT: sll a1, a1, a5 -; RV32I-NEXT: sll a5, t1, a5 +; RV32I-NEXT: slli t4, t4, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or a1, a1, t4 +; RV32I-NEXT: mv t2, sp +; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: or a4, t0, a7 +; RV32I-NEXT: or a5, t3, a5 +; RV32I-NEXT: or a0, a0, a6 +; RV32I-NEXT: or a1, a1, t1 +; RV32I-NEXT: sw a3, 0(sp) +; RV32I-NEXT: sw a4, 4(sp) +; RV32I-NEXT: sw a5, 8(sp) +; RV32I-NEXT: sw a0, 12(sp) +; RV32I-NEXT: srli a0, a1, 3 +; RV32I-NEXT: andi a3, a1, 31 +; RV32I-NEXT: andi a0, a0, 12 +; RV32I-NEXT: xori a3, a3, 31 +; RV32I-NEXT: add a0, t2, a0 +; RV32I-NEXT: lw a4, 4(a0) +; RV32I-NEXT: lw a5, 8(a0) +; RV32I-NEXT: lw a6, 0(a0) +; RV32I-NEXT: lw a0, 12(a0) +; RV32I-NEXT: srl a7, a4, a1 +; RV32I-NEXT: slli t0, a5, 1 +; RV32I-NEXT: srl a6, a6, a1 +; RV32I-NEXT: slli a4, a4, 1 +; RV32I-NEXT: srl a5, a5, a1 +; RV32I-NEXT: slli t1, a0, 1 +; RV32I-NEXT: srl a0, a0, a1 +; RV32I-NEXT: sll a1, t0, a3 +; RV32I-NEXT: sll a4, a4, a3 +; RV32I-NEXT: sll a3, t1, a3 ; RV32I-NEXT: srli t0, a0, 16 ; RV32I-NEXT: srli t1, a0, 24 ; RV32I-NEXT: srli t2, a0, 8 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a1, a4, a1 -; RV32I-NEXT: or a3, a3, a5 +; RV32I-NEXT: or a1, a7, a1 +; RV32I-NEXT: or a4, a6, a4 +; RV32I-NEXT: or a3, a5, a3 ; RV32I-NEXT: sb a0, 12(a2) ; RV32I-NEXT: sb t2, 13(a2) ; RV32I-NEXT: sb t0, 14(a2) ; RV32I-NEXT: sb t1, 15(a2) ; RV32I-NEXT: srli a0, a3, 16 -; RV32I-NEXT: srli a4, a3, 24 -; RV32I-NEXT: srli a5, a3, 8 -; RV32I-NEXT: srli a7, a1, 16 -; RV32I-NEXT: srli t0, a1, 24 -; RV32I-NEXT: srli t1, a1, 8 -; RV32I-NEXT: srli t2, a6, 16 -; RV32I-NEXT: srli t3, a6, 24 +; RV32I-NEXT: srli a5, a3, 24 +; RV32I-NEXT: srli a6, a3, 8 +; RV32I-NEXT: srli a7, a4, 16 +; RV32I-NEXT: srli t0, a4, 24 +; RV32I-NEXT: srli t1, a4, 8 +; RV32I-NEXT: srli t2, a1, 16 +; RV32I-NEXT: srli t3, a1, 24 ; RV32I-NEXT: sb a3, 8(a2) -; RV32I-NEXT: sb a5, 9(a2) +; RV32I-NEXT: sb a6, 9(a2) ; RV32I-NEXT: sb a0, 10(a2) -; RV32I-NEXT: sb a4, 11(a2) -; RV32I-NEXT: srli a0, a6, 8 -; RV32I-NEXT: sb a1, 0(a2) +; RV32I-NEXT: sb a5, 11(a2) +; RV32I-NEXT: srli a0, a1, 8 +; RV32I-NEXT: sb a4, 0(a2) ; RV32I-NEXT: sb t1, 1(a2) ; RV32I-NEXT: sb a7, 2(a2) ; RV32I-NEXT: sb t0, 3(a2) -; RV32I-NEXT: sb a6, 4(a2) +; RV32I-NEXT: sb a1, 4(a2) ; RV32I-NEXT: sb a0, 5(a2) ; RV32I-NEXT: sb t2, 6(a2) ; RV32I-NEXT: sb t3, 7(a2) @@ -943,93 +952,102 @@ define void @shl_16bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: slli a4, a4, 8 ; RV32I-NEXT: slli a5, a5, 16 ; RV32I-NEXT: slli a6, a6, 24 +; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: or a4, a6, a5 +; RV32I-NEXT: lbu a5, 8(a0) +; RV32I-NEXT: lbu a6, 9(a0) +; RV32I-NEXT: lbu t3, 10(a0) +; RV32I-NEXT: lbu t4, 11(a0) ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: or a4, a4, a3 -; RV32I-NEXT: or a5, a6, a5 -; RV32I-NEXT: or a3, t0, a7 -; RV32I-NEXT: lbu a6, 8(a0) -; RV32I-NEXT: lbu a7, 9(a0) -; RV32I-NEXT: lbu t0, 10(a0) -; RV32I-NEXT: lbu t3, 11(a0) ; RV32I-NEXT: slli t1, t1, 16 ; RV32I-NEXT: slli t2, t2, 24 -; RV32I-NEXT: slli a7, a7, 8 -; RV32I-NEXT: slli t0, t0, 16 -; RV32I-NEXT: slli t3, t3, 24 -; RV32I-NEXT: or t1, t2, t1 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a7, t3, t0 -; RV32I-NEXT: lbu t0, 12(a0) -; RV32I-NEXT: lbu t2, 13(a0) -; RV32I-NEXT: lbu t3, 14(a0) -; RV32I-NEXT: lbu t4, 15(a0) -; RV32I-NEXT: lbu a0, 0(a1) +; RV32I-NEXT: slli a6, a6, 8 +; RV32I-NEXT: or a7, t0, a7 +; RV32I-NEXT: or t0, t2, t1 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: lbu a6, 12(a0) +; RV32I-NEXT: lbu t1, 13(a0) +; RV32I-NEXT: lbu t2, 14(a0) +; RV32I-NEXT: lbu a0, 15(a0) +; RV32I-NEXT: slli t3, t3, 16 +; RV32I-NEXT: slli t4, t4, 24 +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: slli t2, t2, 16 +; RV32I-NEXT: slli a0, a0, 24 +; RV32I-NEXT: or t3, t4, t3 +; RV32I-NEXT: or a6, t1, a6 +; RV32I-NEXT: or a0, a0, t2 +; RV32I-NEXT: lbu t1, 1(a1) +; RV32I-NEXT: lbu t2, 0(a1) +; RV32I-NEXT: lbu t4, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: or t1, t1, t2 ; RV32I-NEXT: sw zero, 0(sp) ; RV32I-NEXT: sw zero, 4(sp) ; RV32I-NEXT: sw zero, 8(sp) ; RV32I-NEXT: sw zero, 12(sp) -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: or a1, t2, t0 -; RV32I-NEXT: addi t0, sp, 16 -; RV32I-NEXT: slli t3, t3, 16 -; RV32I-NEXT: slli t4, t4, 24 -; RV32I-NEXT: or t2, t4, t3 -; RV32I-NEXT: srli t3, a0, 3 -; RV32I-NEXT: or a4, a5, a4 -; RV32I-NEXT: andi a5, a0, 31 -; RV32I-NEXT: andi t3, t3, 12 -; RV32I-NEXT: or a3, t1, a3 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a1, t2, a1 -; RV32I-NEXT: sub a7, t0, t3 -; RV32I-NEXT: sw a4, 16(sp) -; RV32I-NEXT: sw a3, 20(sp) -; RV32I-NEXT: sw a6, 24(sp) -; RV32I-NEXT: sw a1, 28(sp) -; RV32I-NEXT: lw a1, 0(a7) -; RV32I-NEXT: lw a3, 4(a7) -; RV32I-NEXT: lw a4, 8(a7) -; RV32I-NEXT: lw a6, 12(a7) -; RV32I-NEXT: xori a5, a5, 31 -; RV32I-NEXT: sll a7, a3, a0 -; RV32I-NEXT: srli t0, a1, 1 -; RV32I-NEXT: sll a6, a6, a0 -; RV32I-NEXT: srli t1, a4, 1 -; RV32I-NEXT: sll a4, a4, a0 -; RV32I-NEXT: srli a3, a3, 1 -; RV32I-NEXT: sll a0, a1, a0 -; RV32I-NEXT: srl a1, t0, a5 -; RV32I-NEXT: srl t0, t1, a5 -; RV32I-NEXT: srl a3, a3, a5 -; RV32I-NEXT: srli a5, a0, 16 -; RV32I-NEXT: srli t1, a0, 24 -; RV32I-NEXT: srli t2, a0, 8 -; RV32I-NEXT: or a1, a7, a1 -; RV32I-NEXT: or a6, a6, t0 +; RV32I-NEXT: slli t4, t4, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or a1, a1, t4 +; RV32I-NEXT: addi t2, sp, 16 ; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: sb a0, 0(a2) +; RV32I-NEXT: or a4, t0, a7 +; RV32I-NEXT: or a5, t3, a5 +; RV32I-NEXT: or a0, a0, a6 +; RV32I-NEXT: or a1, a1, t1 +; RV32I-NEXT: sw a3, 16(sp) +; RV32I-NEXT: sw a4, 20(sp) +; RV32I-NEXT: sw a5, 24(sp) +; RV32I-NEXT: sw a0, 28(sp) +; RV32I-NEXT: srli a0, a1, 3 +; RV32I-NEXT: andi a3, a1, 31 +; RV32I-NEXT: andi a0, a0, 12 +; RV32I-NEXT: sub a0, t2, a0 +; RV32I-NEXT: lw a4, 0(a0) +; RV32I-NEXT: lw a5, 4(a0) +; RV32I-NEXT: lw a6, 8(a0) +; RV32I-NEXT: lw a0, 12(a0) +; RV32I-NEXT: xori a3, a3, 31 +; RV32I-NEXT: sll a7, a5, a1 +; RV32I-NEXT: srli t0, a4, 1 +; RV32I-NEXT: sll a0, a0, a1 +; RV32I-NEXT: srli t1, a6, 1 +; RV32I-NEXT: sll a6, a6, a1 +; RV32I-NEXT: srli a5, a5, 1 +; RV32I-NEXT: sll a1, a4, a1 +; RV32I-NEXT: srl a4, t0, a3 +; RV32I-NEXT: srl t0, t1, a3 +; RV32I-NEXT: srl a3, a5, a3 +; RV32I-NEXT: srli a5, a1, 16 +; RV32I-NEXT: srli t1, a1, 24 +; RV32I-NEXT: srli t2, a1, 8 +; RV32I-NEXT: or a4, a7, a4 +; RV32I-NEXT: or a0, a0, t0 +; RV32I-NEXT: or a3, a6, a3 +; RV32I-NEXT: sb a1, 0(a2) ; RV32I-NEXT: sb t2, 1(a2) ; RV32I-NEXT: sb a5, 2(a2) ; RV32I-NEXT: sb t1, 3(a2) -; RV32I-NEXT: srli a0, a3, 16 -; RV32I-NEXT: srli a4, a3, 24 -; RV32I-NEXT: srli a5, a3, 8 -; RV32I-NEXT: srli a7, a6, 16 -; RV32I-NEXT: srli t0, a6, 24 -; RV32I-NEXT: srli t1, a6, 8 -; RV32I-NEXT: srli t2, a1, 16 -; RV32I-NEXT: srli t3, a1, 24 +; RV32I-NEXT: srli a1, a3, 16 +; RV32I-NEXT: srli a5, a3, 24 +; RV32I-NEXT: srli a6, a3, 8 +; RV32I-NEXT: srli a7, a0, 16 +; RV32I-NEXT: srli t0, a0, 24 +; RV32I-NEXT: srli t1, a0, 8 +; RV32I-NEXT: srli t2, a4, 16 +; RV32I-NEXT: srli t3, a4, 24 ; RV32I-NEXT: sb a3, 8(a2) -; RV32I-NEXT: sb a5, 9(a2) -; RV32I-NEXT: sb a0, 10(a2) -; RV32I-NEXT: sb a4, 11(a2) -; RV32I-NEXT: srli a0, a1, 8 -; RV32I-NEXT: sb a6, 12(a2) +; RV32I-NEXT: sb a6, 9(a2) +; RV32I-NEXT: sb a1, 10(a2) +; RV32I-NEXT: sb a5, 11(a2) +; RV32I-NEXT: srli a1, a4, 8 +; RV32I-NEXT: sb a0, 12(a2) ; RV32I-NEXT: sb t1, 13(a2) ; RV32I-NEXT: sb a7, 14(a2) ; RV32I-NEXT: sb t0, 15(a2) -; RV32I-NEXT: sb a1, 4(a2) -; RV32I-NEXT: sb a0, 5(a2) +; RV32I-NEXT: sb a4, 4(a2) +; RV32I-NEXT: sb a1, 5(a2) ; RV32I-NEXT: sb t2, 6(a2) ; RV32I-NEXT: sb t3, 7(a2) ; RV32I-NEXT: addi sp, sp, 32 @@ -1168,73 +1186,82 @@ define void @ashr_16bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: lbu t1, 6(a0) ; RV32I-NEXT: lbu t2, 7(a0) ; RV32I-NEXT: slli a4, a4, 8 +; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: lbu a4, 8(a0) +; RV32I-NEXT: lbu t3, 9(a0) +; RV32I-NEXT: lbu t4, 10(a0) +; RV32I-NEXT: lbu t5, 11(a0) ; RV32I-NEXT: slli a5, a5, 16 ; RV32I-NEXT: slli a6, a6, 24 ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: or a4, a6, a5 -; RV32I-NEXT: or a5, t0, a7 -; RV32I-NEXT: lbu a6, 8(a0) -; RV32I-NEXT: lbu a7, 9(a0) -; RV32I-NEXT: lbu t0, 10(a0) -; RV32I-NEXT: lbu t3, 11(a0) ; RV32I-NEXT: slli t1, t1, 16 ; RV32I-NEXT: slli t2, t2, 24 -; RV32I-NEXT: slli a7, a7, 8 -; RV32I-NEXT: slli t0, t0, 16 -; RV32I-NEXT: slli t3, t3, 24 -; RV32I-NEXT: or t1, t2, t1 -; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a7, t3, t0 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: or a6, t0, a7 +; RV32I-NEXT: or a7, t2, t1 ; RV32I-NEXT: lbu t0, 12(a0) -; RV32I-NEXT: lbu t2, 13(a0) -; RV32I-NEXT: lbu t3, 14(a0) -; RV32I-NEXT: lbu t4, 15(a0) -; RV32I-NEXT: lbu a0, 0(a1) -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: or a1, t2, t0 -; RV32I-NEXT: mv t0, sp -; RV32I-NEXT: slli t3, t3, 16 -; RV32I-NEXT: slli t4, t4, 24 -; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: srli a4, a0, 3 -; RV32I-NEXT: or a5, t1, a5 -; RV32I-NEXT: andi t1, a0, 31 -; RV32I-NEXT: or t2, t4, t3 -; RV32I-NEXT: srai t3, t4, 31 -; RV32I-NEXT: andi a4, a4, 12 -; RV32I-NEXT: xori t1, t1, 31 +; RV32I-NEXT: lbu t1, 13(a0) +; RV32I-NEXT: lbu t2, 14(a0) +; RV32I-NEXT: lbu a0, 15(a0) +; RV32I-NEXT: slli t3, t3, 8 +; RV32I-NEXT: slli t4, t4, 16 +; RV32I-NEXT: slli t5, t5, 24 +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: or a4, t3, a4 +; RV32I-NEXT: or t3, t5, t4 +; RV32I-NEXT: or t0, t1, t0 +; RV32I-NEXT: lbu t1, 1(a1) +; RV32I-NEXT: lbu t4, 0(a1) +; RV32I-NEXT: lbu t5, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) +; RV32I-NEXT: slli t1, t1, 8 +; RV32I-NEXT: or t1, t1, t4 +; RV32I-NEXT: slli t5, t5, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or a1, a1, t5 +; RV32I-NEXT: or a3, a5, a3 +; RV32I-NEXT: mv a5, sp +; RV32I-NEXT: slli t2, t2, 16 +; RV32I-NEXT: slli a0, a0, 24 +; RV32I-NEXT: or t2, a0, t2 +; RV32I-NEXT: srai a0, a0, 31 ; RV32I-NEXT: or a6, a7, a6 -; RV32I-NEXT: or a1, t2, a1 -; RV32I-NEXT: sw t3, 16(sp) -; RV32I-NEXT: sw t3, 20(sp) -; RV32I-NEXT: sw t3, 24(sp) -; RV32I-NEXT: sw t3, 28(sp) -; RV32I-NEXT: add a4, t0, a4 +; RV32I-NEXT: or a4, t3, a4 +; RV32I-NEXT: or a7, t2, t0 +; RV32I-NEXT: or a1, a1, t1 +; RV32I-NEXT: sw a0, 16(sp) +; RV32I-NEXT: sw a0, 20(sp) +; RV32I-NEXT: sw a0, 24(sp) +; RV32I-NEXT: sw a0, 28(sp) ; RV32I-NEXT: sw a3, 0(sp) -; RV32I-NEXT: sw a5, 4(sp) -; RV32I-NEXT: sw a6, 8(sp) -; RV32I-NEXT: sw a1, 12(sp) -; RV32I-NEXT: lw a1, 4(a4) -; RV32I-NEXT: lw a3, 8(a4) -; RV32I-NEXT: lw a5, 0(a4) -; RV32I-NEXT: lw a4, 12(a4) -; RV32I-NEXT: srl a6, a1, a0 -; RV32I-NEXT: slli a7, a3, 1 -; RV32I-NEXT: srl a5, a5, a0 -; RV32I-NEXT: slli a1, a1, 1 -; RV32I-NEXT: srl a3, a3, a0 -; RV32I-NEXT: slli t0, a4, 1 -; RV32I-NEXT: sra a0, a4, a0 -; RV32I-NEXT: sll a4, a7, t1 -; RV32I-NEXT: sll a1, a1, t1 -; RV32I-NEXT: sll a7, t0, t1 +; RV32I-NEXT: sw a6, 4(sp) +; RV32I-NEXT: sw a4, 8(sp) +; RV32I-NEXT: sw a7, 12(sp) +; RV32I-NEXT: srli a0, a1, 3 +; RV32I-NEXT: andi a3, a1, 31 +; RV32I-NEXT: andi a0, a0, 12 +; RV32I-NEXT: xori a3, a3, 31 +; RV32I-NEXT: add a0, a5, a0 +; RV32I-NEXT: lw a4, 4(a0) +; RV32I-NEXT: lw a5, 8(a0) +; RV32I-NEXT: lw a6, 0(a0) +; RV32I-NEXT: lw a0, 12(a0) +; RV32I-NEXT: srl a7, a4, a1 +; RV32I-NEXT: slli t0, a5, 1 +; RV32I-NEXT: srl a6, a6, a1 +; RV32I-NEXT: slli a4, a4, 1 +; RV32I-NEXT: srl a5, a5, a1 +; RV32I-NEXT: slli t1, a0, 1 +; RV32I-NEXT: sra a0, a0, a1 +; RV32I-NEXT: sll a1, t0, a3 +; RV32I-NEXT: sll a4, a4, a3 +; RV32I-NEXT: sll a3, t1, a3 ; RV32I-NEXT: srli t0, a0, 16 ; RV32I-NEXT: srli t1, a0, 24 ; RV32I-NEXT: srli t2, a0, 8 +; RV32I-NEXT: or a1, a7, a1 ; RV32I-NEXT: or a4, a6, a4 -; RV32I-NEXT: or a1, a5, a1 -; RV32I-NEXT: or a3, a3, a7 +; RV32I-NEXT: or a3, a5, a3 ; RV32I-NEXT: sb a0, 12(a2) ; RV32I-NEXT: sb t2, 13(a2) ; RV32I-NEXT: sb t0, 14(a2) @@ -1242,21 +1269,21 @@ define void @ashr_16bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: srli a0, a3, 16 ; RV32I-NEXT: srli a5, a3, 24 ; RV32I-NEXT: srli a6, a3, 8 -; RV32I-NEXT: srli a7, a1, 16 -; RV32I-NEXT: srli t0, a1, 24 -; RV32I-NEXT: srli t1, a1, 8 -; RV32I-NEXT: srli t2, a4, 16 -; RV32I-NEXT: srli t3, a4, 24 +; RV32I-NEXT: srli a7, a4, 16 +; RV32I-NEXT: srli t0, a4, 24 +; RV32I-NEXT: srli t1, a4, 8 +; RV32I-NEXT: srli t2, a1, 16 +; RV32I-NEXT: srli t3, a1, 24 ; RV32I-NEXT: sb a3, 8(a2) ; RV32I-NEXT: sb a6, 9(a2) ; RV32I-NEXT: sb a0, 10(a2) ; RV32I-NEXT: sb a5, 11(a2) -; RV32I-NEXT: srli a0, a4, 8 -; RV32I-NEXT: sb a1, 0(a2) +; RV32I-NEXT: srli a0, a1, 8 +; RV32I-NEXT: sb a4, 0(a2) ; RV32I-NEXT: sb t1, 1(a2) ; RV32I-NEXT: sb a7, 2(a2) ; RV32I-NEXT: sb t0, 3(a2) -; RV32I-NEXT: sb a4, 4(a2) +; RV32I-NEXT: sb a1, 4(a2) ; RV32I-NEXT: sb a0, 5(a2) ; RV32I-NEXT: sb t2, 6(a2) ; RV32I-NEXT: sb t3, 7(a2) @@ -1272,17 +1299,19 @@ define void @ashr_16bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-LABEL: lshr_32bytes: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -144 -; RV64I-NEXT: sd s0, 136(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s1, 128(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s2, 120(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s3, 112(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s4, 104(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s5, 96(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s6, 88(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s7, 80(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s8, 72(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s9, 64(sp) # 8-byte Folded Spill +; RV64I-NEXT: addi sp, sp, -160 +; RV64I-NEXT: sd s0, 152(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s1, 144(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s2, 136(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s3, 128(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s4, 120(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s5, 112(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s6, 104(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s7, 96(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s8, 88(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s9, 80(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s10, 72(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s11, 64(sp) # 8-byte Folded Spill ; RV64I-NEXT: lbu a3, 0(a0) ; RV64I-NEXT: lbu a4, 1(a0) ; RV64I-NEXT: lbu a5, 2(a0) @@ -1299,122 +1328,143 @@ define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: lbu s1, 13(a0) ; RV64I-NEXT: lbu s2, 14(a0) ; RV64I-NEXT: lbu s3, 15(a0) -; RV64I-NEXT: slli a4, a4, 8 -; RV64I-NEXT: slli a5, a5, 16 -; RV64I-NEXT: slli a6, a6, 24 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 ; RV64I-NEXT: lbu s4, 16(a0) ; RV64I-NEXT: lbu s5, 17(a0) ; RV64I-NEXT: lbu s6, 18(a0) ; RV64I-NEXT: lbu s7, 19(a0) +; RV64I-NEXT: slli a4, a4, 8 +; RV64I-NEXT: slli s8, a5, 16 +; RV64I-NEXT: slli a6, a6, 24 ; RV64I-NEXT: slli t0, t0, 8 ; RV64I-NEXT: slli t1, t1, 16 ; RV64I-NEXT: slli t2, t2, 24 +; RV64I-NEXT: or a5, a4, a3 +; RV64I-NEXT: or a6, a6, s8 +; RV64I-NEXT: or a3, t0, a7 +; RV64I-NEXT: or a4, t2, t1 +; RV64I-NEXT: lbu s8, 20(a0) +; RV64I-NEXT: lbu s9, 21(a0) +; RV64I-NEXT: lbu s10, 22(a0) +; RV64I-NEXT: lbu s11, 23(a0) ; RV64I-NEXT: slli t4, t4, 8 ; RV64I-NEXT: slli t5, t5, 16 ; RV64I-NEXT: slli t6, t6, 24 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a6, t2, t1 -; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: lbu t5, 20(a0) -; RV64I-NEXT: lbu t6, 21(a0) -; RV64I-NEXT: lbu s8, 22(a0) -; RV64I-NEXT: lbu s9, 23(a0) ; RV64I-NEXT: slli s1, s1, 8 ; RV64I-NEXT: slli s2, s2, 16 ; RV64I-NEXT: slli s3, s3, 24 +; RV64I-NEXT: or a7, t4, t3 +; RV64I-NEXT: or t0, t6, t5 +; RV64I-NEXT: or t1, s1, s0 +; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: lbu t6, 24(a0) +; RV64I-NEXT: lbu s0, 25(a0) +; RV64I-NEXT: lbu s1, 26(a0) +; RV64I-NEXT: lbu s2, 27(a0) ; RV64I-NEXT: slli s5, s5, 8 ; RV64I-NEXT: slli s6, s6, 16 ; RV64I-NEXT: slli s7, s7, 24 -; RV64I-NEXT: or t1, s1, s0 -; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: slli s9, s9, 8 ; RV64I-NEXT: or t3, s5, s4 ; RV64I-NEXT: or t4, s7, s6 -; RV64I-NEXT: lbu s0, 24(a0) -; RV64I-NEXT: lbu s1, 25(a0) -; RV64I-NEXT: lbu s2, 26(a0) -; RV64I-NEXT: lbu s3, 27(a0) -; RV64I-NEXT: slli t6, t6, 8 -; RV64I-NEXT: slli s8, s8, 16 -; RV64I-NEXT: slli s9, s9, 24 -; RV64I-NEXT: slli s1, s1, 8 -; RV64I-NEXT: or t5, t6, t5 -; RV64I-NEXT: or t6, s9, s8 -; RV64I-NEXT: or s0, s1, s0 -; RV64I-NEXT: lbu s1, 28(a0) +; RV64I-NEXT: or t5, s9, s8 +; RV64I-NEXT: lbu s3, 28(a0) ; RV64I-NEXT: lbu s4, 29(a0) ; RV64I-NEXT: lbu s5, 30(a0) ; RV64I-NEXT: lbu s6, 31(a0) -; RV64I-NEXT: lbu a0, 0(a1) +; RV64I-NEXT: slli s10, s10, 16 +; RV64I-NEXT: slli s11, s11, 24 +; RV64I-NEXT: slli s0, s0, 8 +; RV64I-NEXT: slli s1, s1, 16 +; RV64I-NEXT: slli s2, s2, 24 +; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or a0, s11, s10 +; RV64I-NEXT: or t6, s0, t6 +; RV64I-NEXT: or s0, s2, s1 +; RV64I-NEXT: or s1, s4, s3 +; RV64I-NEXT: lbu s2, 0(a1) +; RV64I-NEXT: lbu s3, 1(a1) +; RV64I-NEXT: lbu s4, 2(a1) +; RV64I-NEXT: lbu s7, 3(a1) +; RV64I-NEXT: slli s5, s5, 16 +; RV64I-NEXT: slli s6, s6, 24 +; RV64I-NEXT: slli s3, s3, 8 +; RV64I-NEXT: slli s4, s4, 16 +; RV64I-NEXT: slli s7, s7, 24 +; RV64I-NEXT: or s5, s6, s5 +; RV64I-NEXT: or s2, s3, s2 +; RV64I-NEXT: or s3, s7, s4 +; RV64I-NEXT: lbu s4, 5(a1) +; RV64I-NEXT: lbu s6, 4(a1) +; RV64I-NEXT: lbu s7, 6(a1) +; RV64I-NEXT: lbu a1, 7(a1) +; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or s4, s4, s6 +; RV64I-NEXT: slli s7, s7, 16 +; RV64I-NEXT: slli a1, a1, 24 +; RV64I-NEXT: or a1, a1, s7 ; RV64I-NEXT: sd zero, 32(sp) ; RV64I-NEXT: sd zero, 40(sp) ; RV64I-NEXT: sd zero, 48(sp) ; RV64I-NEXT: sd zero, 56(sp) -; RV64I-NEXT: slli s2, s2, 16 -; RV64I-NEXT: slli s3, s3, 24 -; RV64I-NEXT: or a1, s3, s2 -; RV64I-NEXT: mv s2, sp -; RV64I-NEXT: slli s4, s4, 8 -; RV64I-NEXT: slli s5, s5, 16 -; RV64I-NEXT: slli s6, s6, 24 -; RV64I-NEXT: or s1, s4, s1 -; RV64I-NEXT: srli s3, a0, 3 -; RV64I-NEXT: or s4, s6, s5 -; RV64I-NEXT: andi s5, a0, 63 -; RV64I-NEXT: andi s3, s3, 24 -; RV64I-NEXT: xori s5, s5, 63 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a6, t2, t1 -; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: or a1, a1, s0 -; RV64I-NEXT: or t1, s4, s1 -; RV64I-NEXT: add s2, s2, s3 -; RV64I-NEXT: slli a4, a4, 32 -; RV64I-NEXT: slli a6, a6, 32 -; RV64I-NEXT: slli t0, t0, 32 -; RV64I-NEXT: slli t1, t1, 32 +; RV64I-NEXT: or a5, a6, a5 +; RV64I-NEXT: mv a6, sp ; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a1, t1, a1 +; RV64I-NEXT: or a4, t0, a7 +; RV64I-NEXT: or a7, t2, t1 +; RV64I-NEXT: or t0, t4, t3 +; RV64I-NEXT: or a0, a0, t5 +; RV64I-NEXT: or t1, s0, t6 +; RV64I-NEXT: or t2, s5, s1 +; RV64I-NEXT: or t3, s3, s2 +; RV64I-NEXT: or a1, a1, s4 +; RV64I-NEXT: slli a3, a3, 32 +; RV64I-NEXT: slli a7, a7, 32 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: slli t2, t2, 32 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: or a3, a3, a5 +; RV64I-NEXT: or a4, a7, a4 +; RV64I-NEXT: or a0, a0, t0 +; RV64I-NEXT: or a5, t2, t1 +; RV64I-NEXT: or a1, a1, t3 ; RV64I-NEXT: sd a3, 0(sp) ; RV64I-NEXT: sd a4, 8(sp) -; RV64I-NEXT: sd a5, 16(sp) -; RV64I-NEXT: sd a1, 24(sp) -; RV64I-NEXT: ld a1, 8(s2) -; RV64I-NEXT: ld a3, 16(s2) -; RV64I-NEXT: ld a4, 0(s2) -; RV64I-NEXT: ld a5, 24(s2) -; RV64I-NEXT: srl a6, a1, a0 -; RV64I-NEXT: slli a7, a3, 1 -; RV64I-NEXT: srl a4, a4, a0 -; RV64I-NEXT: slli a1, a1, 1 -; RV64I-NEXT: srl a3, a3, a0 +; RV64I-NEXT: sd a0, 16(sp) +; RV64I-NEXT: sd a5, 24(sp) +; RV64I-NEXT: srli a0, a1, 3 +; RV64I-NEXT: andi a3, a1, 63 +; RV64I-NEXT: andi a0, a0, 24 +; RV64I-NEXT: xori a3, a3, 63 +; RV64I-NEXT: add a0, a6, a0 +; RV64I-NEXT: ld a4, 8(a0) +; RV64I-NEXT: ld a5, 16(a0) +; RV64I-NEXT: ld a6, 0(a0) +; RV64I-NEXT: ld a0, 24(a0) +; RV64I-NEXT: srl a7, a4, a1 ; RV64I-NEXT: slli t0, a5, 1 -; RV64I-NEXT: srl a5, a5, a0 -; RV64I-NEXT: sll a0, a7, s5 -; RV64I-NEXT: sll a1, a1, s5 -; RV64I-NEXT: sll a7, t0, s5 -; RV64I-NEXT: srli t0, a5, 56 -; RV64I-NEXT: srli t1, a5, 48 -; RV64I-NEXT: srli t2, a5, 40 -; RV64I-NEXT: srli t3, a5, 32 -; RV64I-NEXT: srli t4, a5, 24 -; RV64I-NEXT: srli t5, a5, 16 -; RV64I-NEXT: srli t6, a5, 8 -; RV64I-NEXT: or a0, a6, a0 -; RV64I-NEXT: or a1, a4, a1 -; RV64I-NEXT: or a3, a3, a7 +; RV64I-NEXT: srl a6, a6, a1 +; RV64I-NEXT: slli a4, a4, 1 +; RV64I-NEXT: srl a5, a5, a1 +; RV64I-NEXT: slli t1, a0, 1 +; RV64I-NEXT: srl t2, a0, a1 +; RV64I-NEXT: sll a0, t0, a3 +; RV64I-NEXT: sll a1, a4, a3 +; RV64I-NEXT: sll a3, t1, a3 +; RV64I-NEXT: srli a4, t2, 56 +; RV64I-NEXT: srli t0, t2, 48 +; RV64I-NEXT: srli t1, t2, 40 +; RV64I-NEXT: srli t3, t2, 32 +; RV64I-NEXT: srli t4, t2, 24 +; RV64I-NEXT: srli t5, t2, 16 +; RV64I-NEXT: srli t6, t2, 8 +; RV64I-NEXT: or a0, a7, a0 +; RV64I-NEXT: or a1, a6, a1 +; RV64I-NEXT: or a3, a5, a3 ; RV64I-NEXT: sb t3, 28(a2) -; RV64I-NEXT: sb t2, 29(a2) -; RV64I-NEXT: sb t1, 30(a2) -; RV64I-NEXT: sb t0, 31(a2) -; RV64I-NEXT: sb a5, 24(a2) +; RV64I-NEXT: sb t1, 29(a2) +; RV64I-NEXT: sb t0, 30(a2) +; RV64I-NEXT: sb a4, 31(a2) +; RV64I-NEXT: sb t2, 24(a2) ; RV64I-NEXT: sb t6, 25(a2) ; RV64I-NEXT: sb t5, 26(a2) ; RV64I-NEXT: sb t4, 27(a2) @@ -1463,17 +1513,19 @@ define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: sb a1, 9(a2) ; RV64I-NEXT: sb a5, 10(a2) ; RV64I-NEXT: sb a3, 11(a2) -; RV64I-NEXT: ld s0, 136(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s1, 128(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s2, 120(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s3, 112(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s4, 104(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s5, 96(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s6, 88(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s7, 80(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s8, 72(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s9, 64(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 144 +; RV64I-NEXT: ld s0, 152(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s1, 144(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s2, 136(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s3, 128(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s4, 120(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s5, 112(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s6, 104(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s7, 96(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s8, 88(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s9, 80(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s10, 72(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s11, 64(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 160 ; RV64I-NEXT: ret ; ; RV32I-LABEL: lshr_32bytes: @@ -1498,55 +1550,67 @@ define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: lbu a7, 3(a0) ; RV32I-NEXT: lbu a5, 4(a0) ; RV32I-NEXT: lbu t0, 5(a0) -; RV32I-NEXT: lbu t3, 6(a0) -; RV32I-NEXT: lbu t6, 7(a0) -; RV32I-NEXT: lbu s2, 8(a0) -; RV32I-NEXT: lbu s3, 9(a0) -; RV32I-NEXT: lbu s4, 10(a0) -; RV32I-NEXT: lbu s5, 11(a0) -; RV32I-NEXT: lbu s7, 12(a0) -; RV32I-NEXT: lbu s8, 13(a0) -; RV32I-NEXT: lbu s9, 14(a0) -; RV32I-NEXT: lbu s10, 15(a0) -; RV32I-NEXT: lbu s11, 16(a0) -; RV32I-NEXT: lbu ra, 17(a0) -; RV32I-NEXT: lbu t4, 18(a0) -; RV32I-NEXT: lbu s0, 19(a0) +; RV32I-NEXT: lbu t1, 6(a0) +; RV32I-NEXT: lbu t2, 7(a0) +; RV32I-NEXT: lbu t3, 8(a0) +; RV32I-NEXT: lbu t4, 9(a0) +; RV32I-NEXT: lbu t5, 10(a0) +; RV32I-NEXT: lbu t6, 11(a0) +; RV32I-NEXT: lbu s0, 12(a0) +; RV32I-NEXT: lbu s2, 13(a0) +; RV32I-NEXT: lbu s4, 14(a0) +; RV32I-NEXT: lbu s5, 15(a0) +; RV32I-NEXT: lbu s6, 16(a0) +; RV32I-NEXT: lbu s7, 17(a0) +; RV32I-NEXT: lbu s8, 18(a0) +; RV32I-NEXT: lbu s9, 19(a0) ; RV32I-NEXT: slli a4, a4, 8 ; RV32I-NEXT: slli a6, a6, 16 ; RV32I-NEXT: slli a7, a7, 24 ; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: sw a3, 4(sp) # 4-byte Folded Spill ; RV32I-NEXT: or a4, a7, a6 -; RV32I-NEXT: lbu t1, 20(a0) -; RV32I-NEXT: lbu t2, 21(a0) -; RV32I-NEXT: lbu t5, 22(a0) -; RV32I-NEXT: lbu s1, 23(a0) +; RV32I-NEXT: lbu s10, 20(a0) +; RV32I-NEXT: lbu s11, 21(a0) +; RV32I-NEXT: lbu ra, 22(a0) +; RV32I-NEXT: lbu a3, 23(a0) ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: slli t3, t3, 16 +; RV32I-NEXT: slli t1, t1, 16 +; RV32I-NEXT: slli t2, t2, 24 +; RV32I-NEXT: slli t4, t4, 8 +; RV32I-NEXT: slli t5, t5, 16 ; RV32I-NEXT: slli t6, t6, 24 -; RV32I-NEXT: slli s3, s3, 8 +; RV32I-NEXT: or a5, t0, a5 +; RV32I-NEXT: or a6, t2, t1 +; RV32I-NEXT: or a7, t4, t3 +; RV32I-NEXT: or t0, t6, t5 +; RV32I-NEXT: lbu s1, 24(a0) +; RV32I-NEXT: lbu s3, 25(a0) +; RV32I-NEXT: lbu t4, 26(a0) +; RV32I-NEXT: lbu t5, 27(a0) +; RV32I-NEXT: slli s2, s2, 8 ; RV32I-NEXT: slli s4, s4, 16 ; RV32I-NEXT: slli s5, s5, 24 -; RV32I-NEXT: or a5, t0, a5 -; RV32I-NEXT: or a6, t6, t3 -; RV32I-NEXT: or a7, s3, s2 -; RV32I-NEXT: or t0, s5, s4 -; RV32I-NEXT: lbu t3, 24(a0) -; RV32I-NEXT: lbu s5, 25(a0) -; RV32I-NEXT: lbu s6, 26(a0) -; RV32I-NEXT: lbu t6, 27(a0) -; RV32I-NEXT: slli s8, s8, 8 -; RV32I-NEXT: slli s9, s9, 16 -; RV32I-NEXT: slli s10, s10, 24 -; RV32I-NEXT: slli ra, ra, 8 -; RV32I-NEXT: or s7, s8, s7 -; RV32I-NEXT: or s2, s10, s9 -; RV32I-NEXT: or s3, ra, s11 -; RV32I-NEXT: lbu s4, 28(a0) -; RV32I-NEXT: lbu s8, 29(a0) -; RV32I-NEXT: lbu s9, 30(a0) -; RV32I-NEXT: lbu s10, 31(a0) -; RV32I-NEXT: lbu a0, 0(a1) +; RV32I-NEXT: slli s7, s7, 8 +; RV32I-NEXT: or t1, s2, s0 +; RV32I-NEXT: or t2, s5, s4 +; RV32I-NEXT: or t3, s7, s6 +; RV32I-NEXT: lbu t6, 28(a0) +; RV32I-NEXT: lbu s4, 29(a0) +; RV32I-NEXT: lbu s5, 30(a0) +; RV32I-NEXT: lbu s6, 31(a0) +; RV32I-NEXT: slli s8, s8, 16 +; RV32I-NEXT: slli s9, s9, 24 +; RV32I-NEXT: slli s11, s11, 8 +; RV32I-NEXT: slli ra, ra, 16 +; RV32I-NEXT: slli a3, a3, 24 +; RV32I-NEXT: or a0, s9, s8 +; RV32I-NEXT: or s0, s11, s10 +; RV32I-NEXT: or s2, a3, ra +; RV32I-NEXT: lbu a3, 0(a1) +; RV32I-NEXT: lbu s7, 1(a1) +; RV32I-NEXT: lbu s8, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) ; RV32I-NEXT: sw zero, 56(sp) ; RV32I-NEXT: sw zero, 60(sp) ; RV32I-NEXT: sw zero, 64(sp) @@ -1555,90 +1619,89 @@ define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: sw zero, 44(sp) ; RV32I-NEXT: sw zero, 48(sp) ; RV32I-NEXT: sw zero, 52(sp) +; RV32I-NEXT: slli s3, s3, 8 +; RV32I-NEXT: or s1, s3, s1 +; RV32I-NEXT: addi s3, sp, 8 ; RV32I-NEXT: slli t4, t4, 16 -; RV32I-NEXT: slli s0, s0, 24 -; RV32I-NEXT: or t4, s0, t4 -; RV32I-NEXT: addi s0, sp, 8 -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: slli t5, t5, 16 -; RV32I-NEXT: slli s1, s1, 24 -; RV32I-NEXT: slli s5, s5, 8 -; RV32I-NEXT: slli s6, s6, 16 -; RV32I-NEXT: slli t6, t6, 24 -; RV32I-NEXT: slli s8, s8, 8 -; RV32I-NEXT: slli s9, s9, 16 -; RV32I-NEXT: slli s10, s10, 24 -; RV32I-NEXT: or t1, t2, t1 +; RV32I-NEXT: slli t5, t5, 24 +; RV32I-NEXT: slli s4, s4, 8 +; RV32I-NEXT: slli s5, s5, 16 +; RV32I-NEXT: slli s6, s6, 24 +; RV32I-NEXT: slli s7, s7, 8 +; RV32I-NEXT: slli s8, s8, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or t4, t5, t4 +; RV32I-NEXT: or t5, s4, t6 +; RV32I-NEXT: or t6, s6, s5 +; RV32I-NEXT: or a3, s7, a3 +; RV32I-NEXT: or a1, a1, s8 +; RV32I-NEXT: lw s4, 4(sp) # 4-byte Folded Reload +; RV32I-NEXT: or a4, a4, s4 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: or a6, t0, a7 +; RV32I-NEXT: or a7, t2, t1 +; RV32I-NEXT: or t0, a0, t3 +; RV32I-NEXT: or t1, s2, s0 +; RV32I-NEXT: or t2, t4, s1 +; RV32I-NEXT: or t3, t6, t5 +; RV32I-NEXT: or a0, a1, a3 +; RV32I-NEXT: sw t0, 24(sp) +; RV32I-NEXT: sw t1, 28(sp) +; RV32I-NEXT: sw t2, 32(sp) +; RV32I-NEXT: sw t3, 36(sp) +; RV32I-NEXT: sw a4, 8(sp) +; RV32I-NEXT: sw a5, 12(sp) +; RV32I-NEXT: sw a6, 16(sp) +; RV32I-NEXT: sw a7, 20(sp) ; RV32I-NEXT: srli a1, a0, 3 -; RV32I-NEXT: or t2, s1, t5 -; RV32I-NEXT: andi t5, a0, 31 -; RV32I-NEXT: or t3, s5, t3 -; RV32I-NEXT: or t6, t6, s6 -; RV32I-NEXT: or s1, s8, s4 -; RV32I-NEXT: or s4, s10, s9 -; RV32I-NEXT: andi s5, a1, 28 -; RV32I-NEXT: xori a1, t5, 31 -; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: or a4, a6, a5 -; RV32I-NEXT: or a5, t0, a7 -; RV32I-NEXT: or a6, s2, s7 -; RV32I-NEXT: or a7, t4, s3 -; RV32I-NEXT: or t0, t2, t1 -; RV32I-NEXT: or t1, t6, t3 -; RV32I-NEXT: or t2, s4, s1 -; RV32I-NEXT: add s0, s0, s5 -; RV32I-NEXT: sw a7, 24(sp) -; RV32I-NEXT: sw t0, 28(sp) -; RV32I-NEXT: sw t1, 32(sp) -; RV32I-NEXT: sw t2, 36(sp) -; RV32I-NEXT: sw a3, 8(sp) -; RV32I-NEXT: sw a4, 12(sp) -; RV32I-NEXT: sw a5, 16(sp) -; RV32I-NEXT: sw a6, 20(sp) -; RV32I-NEXT: lw a3, 0(s0) -; RV32I-NEXT: lw a4, 4(s0) -; RV32I-NEXT: lw a5, 8(s0) -; RV32I-NEXT: lw a6, 12(s0) -; RV32I-NEXT: lw a7, 16(s0) -; RV32I-NEXT: lw t0, 20(s0) -; RV32I-NEXT: lw t1, 24(s0) -; RV32I-NEXT: lw t2, 28(s0) -; RV32I-NEXT: srl t3, a4, a0 -; RV32I-NEXT: slli t4, a5, 1 +; RV32I-NEXT: andi a3, a0, 31 +; RV32I-NEXT: andi a4, a1, 28 +; RV32I-NEXT: xori a1, a3, 31 +; RV32I-NEXT: add a4, s3, a4 +; RV32I-NEXT: lw a3, 0(a4) +; RV32I-NEXT: lw a5, 4(a4) +; RV32I-NEXT: lw a6, 8(a4) +; RV32I-NEXT: lw a7, 12(a4) +; RV32I-NEXT: lw t0, 16(a4) +; RV32I-NEXT: lw t1, 20(a4) +; RV32I-NEXT: lw t2, 24(a4) +; RV32I-NEXT: lw a4, 28(a4) +; RV32I-NEXT: srl t3, a5, a0 +; RV32I-NEXT: slli t4, a6, 1 ; RV32I-NEXT: srl a3, a3, a0 -; RV32I-NEXT: slli a4, a4, 1 -; RV32I-NEXT: srl t5, a6, a0 -; RV32I-NEXT: slli t6, a7, 1 -; RV32I-NEXT: srl a5, a5, a0 -; RV32I-NEXT: slli a6, a6, 1 -; RV32I-NEXT: srl s0, t0, a0 -; RV32I-NEXT: slli s1, t1, 1 -; RV32I-NEXT: srl a7, a7, a0 -; RV32I-NEXT: slli t0, t0, 1 -; RV32I-NEXT: srl t1, t1, a0 -; RV32I-NEXT: slli s2, t2, 1 +; RV32I-NEXT: slli a5, a5, 1 +; RV32I-NEXT: srl t5, a7, a0 +; RV32I-NEXT: slli t6, t0, 1 +; RV32I-NEXT: srl a6, a6, a0 +; RV32I-NEXT: slli a7, a7, 1 +; RV32I-NEXT: srl s0, t1, a0 +; RV32I-NEXT: slli s1, t2, 1 +; RV32I-NEXT: srl t0, t0, a0 +; RV32I-NEXT: slli t1, t1, 1 ; RV32I-NEXT: srl t2, t2, a0 +; RV32I-NEXT: slli s2, a4, 1 +; RV32I-NEXT: srl s3, a4, a0 ; RV32I-NEXT: sll a0, t4, a1 -; RV32I-NEXT: sll a4, a4, a1 -; RV32I-NEXT: sll t4, t6, a1 -; RV32I-NEXT: sll a6, a6, a1 -; RV32I-NEXT: sll t6, s1, a1 -; RV32I-NEXT: sll t0, t0, a1 -; RV32I-NEXT: sll s1, s2, a1 -; RV32I-NEXT: srli s2, t2, 24 -; RV32I-NEXT: srli s3, t2, 16 -; RV32I-NEXT: srli s4, t2, 8 +; RV32I-NEXT: sll a4, a5, a1 +; RV32I-NEXT: sll a5, t6, a1 +; RV32I-NEXT: sll a7, a7, a1 +; RV32I-NEXT: sll t4, s1, a1 +; RV32I-NEXT: sll t1, t1, a1 +; RV32I-NEXT: sll t6, s2, a1 +; RV32I-NEXT: srli s1, s3, 24 +; RV32I-NEXT: srli s2, s3, 16 +; RV32I-NEXT: srli s4, s3, 8 ; RV32I-NEXT: or a0, t3, a0 ; RV32I-NEXT: or a1, a3, a4 -; RV32I-NEXT: or a3, t5, t4 -; RV32I-NEXT: or a4, a5, a6 -; RV32I-NEXT: or a5, s0, t6 -; RV32I-NEXT: or a6, a7, t0 -; RV32I-NEXT: or a7, t1, s1 -; RV32I-NEXT: sb t2, 28(a2) +; RV32I-NEXT: or a3, t5, a5 +; RV32I-NEXT: or a4, a6, a7 +; RV32I-NEXT: or a5, s0, t4 +; RV32I-NEXT: or a6, t0, t1 +; RV32I-NEXT: or a7, t2, t6 +; RV32I-NEXT: sb s3, 28(a2) ; RV32I-NEXT: sb s4, 29(a2) -; RV32I-NEXT: sb s3, 30(a2) -; RV32I-NEXT: sb s2, 31(a2) +; RV32I-NEXT: sb s2, 30(a2) +; RV32I-NEXT: sb s1, 31(a2) ; RV32I-NEXT: srli t0, a7, 24 ; RV32I-NEXT: srli t1, a7, 16 ; RV32I-NEXT: srli t2, a7, 8 @@ -1712,17 +1775,19 @@ define void @lshr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-LABEL: shl_32bytes: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -144 -; RV64I-NEXT: sd s0, 136(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s1, 128(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s2, 120(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s3, 112(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s4, 104(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s5, 96(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s6, 88(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s7, 80(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s8, 72(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s9, 64(sp) # 8-byte Folded Spill +; RV64I-NEXT: addi sp, sp, -160 +; RV64I-NEXT: sd s0, 152(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s1, 144(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s2, 136(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s3, 128(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s4, 120(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s5, 112(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s6, 104(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s7, 96(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s8, 88(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s9, 80(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s10, 72(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s11, 64(sp) # 8-byte Folded Spill ; RV64I-NEXT: lbu a3, 0(a0) ; RV64I-NEXT: lbu a4, 1(a0) ; RV64I-NEXT: lbu a5, 2(a0) @@ -1739,125 +1804,146 @@ define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: lbu s1, 13(a0) ; RV64I-NEXT: lbu s2, 14(a0) ; RV64I-NEXT: lbu s3, 15(a0) -; RV64I-NEXT: slli a4, a4, 8 -; RV64I-NEXT: slli a5, a5, 16 -; RV64I-NEXT: slli a6, a6, 24 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 ; RV64I-NEXT: lbu s4, 16(a0) ; RV64I-NEXT: lbu s5, 17(a0) ; RV64I-NEXT: lbu s6, 18(a0) ; RV64I-NEXT: lbu s7, 19(a0) +; RV64I-NEXT: slli a4, a4, 8 +; RV64I-NEXT: slli s8, a5, 16 +; RV64I-NEXT: slli a6, a6, 24 ; RV64I-NEXT: slli t0, t0, 8 ; RV64I-NEXT: slli t1, t1, 16 ; RV64I-NEXT: slli t2, t2, 24 +; RV64I-NEXT: or a5, a4, a3 +; RV64I-NEXT: or a6, a6, s8 +; RV64I-NEXT: or a3, t0, a7 +; RV64I-NEXT: or a4, t2, t1 +; RV64I-NEXT: lbu s8, 20(a0) +; RV64I-NEXT: lbu s9, 21(a0) +; RV64I-NEXT: lbu s10, 22(a0) +; RV64I-NEXT: lbu s11, 23(a0) ; RV64I-NEXT: slli t4, t4, 8 ; RV64I-NEXT: slli t5, t5, 16 ; RV64I-NEXT: slli t6, t6, 24 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a6, t2, t1 -; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: lbu t5, 20(a0) -; RV64I-NEXT: lbu t6, 21(a0) -; RV64I-NEXT: lbu s8, 22(a0) -; RV64I-NEXT: lbu s9, 23(a0) ; RV64I-NEXT: slli s1, s1, 8 ; RV64I-NEXT: slli s2, s2, 16 ; RV64I-NEXT: slli s3, s3, 24 +; RV64I-NEXT: or a7, t4, t3 +; RV64I-NEXT: or t0, t6, t5 +; RV64I-NEXT: or t1, s1, s0 +; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: lbu t6, 24(a0) +; RV64I-NEXT: lbu s0, 25(a0) +; RV64I-NEXT: lbu s1, 26(a0) +; RV64I-NEXT: lbu s2, 27(a0) ; RV64I-NEXT: slli s5, s5, 8 ; RV64I-NEXT: slli s6, s6, 16 ; RV64I-NEXT: slli s7, s7, 24 -; RV64I-NEXT: or t1, s1, s0 -; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: slli s9, s9, 8 ; RV64I-NEXT: or t3, s5, s4 ; RV64I-NEXT: or t4, s7, s6 -; RV64I-NEXT: lbu s0, 24(a0) -; RV64I-NEXT: lbu s1, 25(a0) -; RV64I-NEXT: lbu s2, 26(a0) -; RV64I-NEXT: lbu s3, 27(a0) -; RV64I-NEXT: slli t6, t6, 8 -; RV64I-NEXT: slli s8, s8, 16 -; RV64I-NEXT: slli s9, s9, 24 -; RV64I-NEXT: slli s1, s1, 8 -; RV64I-NEXT: or t5, t6, t5 -; RV64I-NEXT: or t6, s9, s8 -; RV64I-NEXT: or s0, s1, s0 -; RV64I-NEXT: lbu s1, 28(a0) +; RV64I-NEXT: or t5, s9, s8 +; RV64I-NEXT: lbu s3, 28(a0) ; RV64I-NEXT: lbu s4, 29(a0) ; RV64I-NEXT: lbu s5, 30(a0) ; RV64I-NEXT: lbu s6, 31(a0) -; RV64I-NEXT: lbu a0, 0(a1) +; RV64I-NEXT: slli s10, s10, 16 +; RV64I-NEXT: slli s11, s11, 24 +; RV64I-NEXT: slli s0, s0, 8 +; RV64I-NEXT: slli s1, s1, 16 +; RV64I-NEXT: slli s2, s2, 24 +; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or a0, s11, s10 +; RV64I-NEXT: or t6, s0, t6 +; RV64I-NEXT: or s0, s2, s1 +; RV64I-NEXT: or s1, s4, s3 +; RV64I-NEXT: lbu s2, 0(a1) +; RV64I-NEXT: lbu s3, 1(a1) +; RV64I-NEXT: lbu s4, 2(a1) +; RV64I-NEXT: lbu s7, 3(a1) +; RV64I-NEXT: slli s5, s5, 16 +; RV64I-NEXT: slli s6, s6, 24 +; RV64I-NEXT: slli s3, s3, 8 +; RV64I-NEXT: slli s4, s4, 16 +; RV64I-NEXT: slli s7, s7, 24 +; RV64I-NEXT: or s5, s6, s5 +; RV64I-NEXT: or s2, s3, s2 +; RV64I-NEXT: or s3, s7, s4 +; RV64I-NEXT: lbu s4, 5(a1) +; RV64I-NEXT: lbu s6, 4(a1) +; RV64I-NEXT: lbu s7, 6(a1) +; RV64I-NEXT: lbu a1, 7(a1) +; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or s4, s4, s6 +; RV64I-NEXT: slli s7, s7, 16 +; RV64I-NEXT: slli a1, a1, 24 +; RV64I-NEXT: or a1, a1, s7 ; RV64I-NEXT: sd zero, 0(sp) ; RV64I-NEXT: sd zero, 8(sp) ; RV64I-NEXT: sd zero, 16(sp) ; RV64I-NEXT: sd zero, 24(sp) -; RV64I-NEXT: slli s2, s2, 16 -; RV64I-NEXT: slli s3, s3, 24 -; RV64I-NEXT: or a1, s3, s2 -; RV64I-NEXT: addi s2, sp, 32 -; RV64I-NEXT: slli s4, s4, 8 -; RV64I-NEXT: slli s5, s5, 16 -; RV64I-NEXT: slli s6, s6, 24 -; RV64I-NEXT: or s1, s4, s1 -; RV64I-NEXT: srli s3, a0, 3 -; RV64I-NEXT: or s4, s6, s5 -; RV64I-NEXT: andi s5, a0, 63 -; RV64I-NEXT: andi s3, s3, 24 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a6, t2, t1 -; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: or a1, a1, s0 -; RV64I-NEXT: or t1, s4, s1 -; RV64I-NEXT: sub t2, s2, s3 -; RV64I-NEXT: slli a4, a4, 32 -; RV64I-NEXT: slli a6, a6, 32 -; RV64I-NEXT: slli t0, t0, 32 -; RV64I-NEXT: slli t1, t1, 32 +; RV64I-NEXT: or a5, a6, a5 +; RV64I-NEXT: addi a6, sp, 32 ; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a1, t1, a1 +; RV64I-NEXT: or a4, t0, a7 +; RV64I-NEXT: or a7, t2, t1 +; RV64I-NEXT: or t0, t4, t3 +; RV64I-NEXT: or a0, a0, t5 +; RV64I-NEXT: or t1, s0, t6 +; RV64I-NEXT: or t2, s5, s1 +; RV64I-NEXT: or t3, s3, s2 +; RV64I-NEXT: or a1, a1, s4 +; RV64I-NEXT: slli a3, a3, 32 +; RV64I-NEXT: slli a7, a7, 32 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: slli t2, t2, 32 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: or a3, a3, a5 +; RV64I-NEXT: or a4, a7, a4 +; RV64I-NEXT: or a0, a0, t0 +; RV64I-NEXT: or a5, t2, t1 +; RV64I-NEXT: or a1, a1, t3 ; RV64I-NEXT: sd a3, 32(sp) ; RV64I-NEXT: sd a4, 40(sp) -; RV64I-NEXT: sd a5, 48(sp) -; RV64I-NEXT: sd a1, 56(sp) -; RV64I-NEXT: ld a1, 0(t2) -; RV64I-NEXT: ld a3, 8(t2) -; RV64I-NEXT: ld a4, 16(t2) -; RV64I-NEXT: ld a5, 24(t2) -; RV64I-NEXT: xori a6, s5, 63 -; RV64I-NEXT: sll a7, a3, a0 -; RV64I-NEXT: srli t0, a1, 1 -; RV64I-NEXT: sll a5, a5, a0 -; RV64I-NEXT: srli t1, a4, 1 -; RV64I-NEXT: sll a4, a4, a0 -; RV64I-NEXT: srli a3, a3, 1 -; RV64I-NEXT: sll t2, a1, a0 -; RV64I-NEXT: srl a0, t0, a6 -; RV64I-NEXT: srl a1, t1, a6 -; RV64I-NEXT: srl a3, a3, a6 -; RV64I-NEXT: srli a6, t2, 56 -; RV64I-NEXT: srli t0, t2, 48 -; RV64I-NEXT: srli t1, t2, 40 -; RV64I-NEXT: srli t3, t2, 32 -; RV64I-NEXT: srli t4, t2, 24 -; RV64I-NEXT: srli t5, t2, 16 -; RV64I-NEXT: srli t6, t2, 8 -; RV64I-NEXT: or a0, a7, a0 -; RV64I-NEXT: or a1, a5, a1 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: sb t3, 4(a2) -; RV64I-NEXT: sb t1, 5(a2) -; RV64I-NEXT: sb t0, 6(a2) -; RV64I-NEXT: sb a6, 7(a2) -; RV64I-NEXT: sb t2, 0(a2) -; RV64I-NEXT: sb t6, 1(a2) -; RV64I-NEXT: sb t5, 2(a2) -; RV64I-NEXT: sb t4, 3(a2) +; RV64I-NEXT: sd a0, 48(sp) +; RV64I-NEXT: sd a5, 56(sp) +; RV64I-NEXT: srli a0, a1, 3 +; RV64I-NEXT: andi a3, a1, 63 +; RV64I-NEXT: andi a0, a0, 24 +; RV64I-NEXT: sub a0, a6, a0 +; RV64I-NEXT: ld a4, 0(a0) +; RV64I-NEXT: ld a5, 8(a0) +; RV64I-NEXT: ld a6, 16(a0) +; RV64I-NEXT: ld a0, 24(a0) +; RV64I-NEXT: xori a3, a3, 63 +; RV64I-NEXT: sll a7, a5, a1 +; RV64I-NEXT: srli t0, a4, 1 +; RV64I-NEXT: sll t1, a0, a1 +; RV64I-NEXT: srli a0, a6, 1 +; RV64I-NEXT: sll a6, a6, a1 +; RV64I-NEXT: srli a5, a5, 1 +; RV64I-NEXT: sll a4, a4, a1 +; RV64I-NEXT: srl a1, t0, a3 +; RV64I-NEXT: srl t0, a0, a3 +; RV64I-NEXT: srl a3, a5, a3 +; RV64I-NEXT: srli a5, a4, 56 +; RV64I-NEXT: srli t2, a4, 48 +; RV64I-NEXT: srli t3, a4, 40 +; RV64I-NEXT: srli t4, a4, 32 +; RV64I-NEXT: srli t5, a4, 24 +; RV64I-NEXT: srli t6, a4, 16 +; RV64I-NEXT: srli s0, a4, 8 +; RV64I-NEXT: or a0, a7, a1 +; RV64I-NEXT: or a1, t1, t0 +; RV64I-NEXT: or a3, a6, a3 +; RV64I-NEXT: sb t4, 4(a2) +; RV64I-NEXT: sb t3, 5(a2) +; RV64I-NEXT: sb t2, 6(a2) +; RV64I-NEXT: sb a5, 7(a2) +; RV64I-NEXT: sb a4, 0(a2) +; RV64I-NEXT: sb s0, 1(a2) +; RV64I-NEXT: sb t6, 2(a2) +; RV64I-NEXT: sb t5, 3(a2) ; RV64I-NEXT: srli a4, a3, 56 ; RV64I-NEXT: srli a5, a3, 48 ; RV64I-NEXT: srli a6, a3, 40 @@ -1903,17 +1989,19 @@ define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: sb a1, 9(a2) ; RV64I-NEXT: sb a5, 10(a2) ; RV64I-NEXT: sb a3, 11(a2) -; RV64I-NEXT: ld s0, 136(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s1, 128(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s2, 120(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s3, 112(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s4, 104(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s5, 96(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s6, 88(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s7, 80(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s8, 72(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s9, 64(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 144 +; RV64I-NEXT: ld s0, 152(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s1, 144(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s2, 136(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s3, 128(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s4, 120(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s5, 112(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s6, 104(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s7, 96(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s8, 88(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s9, 80(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s10, 72(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s11, 64(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 160 ; RV64I-NEXT: ret ; ; RV32I-LABEL: shl_32bytes: @@ -1938,55 +2026,67 @@ define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: lbu a7, 3(a0) ; RV32I-NEXT: lbu a5, 4(a0) ; RV32I-NEXT: lbu t0, 5(a0) -; RV32I-NEXT: lbu t3, 6(a0) -; RV32I-NEXT: lbu t6, 7(a0) -; RV32I-NEXT: lbu s2, 8(a0) -; RV32I-NEXT: lbu s3, 9(a0) -; RV32I-NEXT: lbu s4, 10(a0) -; RV32I-NEXT: lbu s5, 11(a0) -; RV32I-NEXT: lbu s7, 12(a0) -; RV32I-NEXT: lbu s8, 13(a0) -; RV32I-NEXT: lbu s9, 14(a0) -; RV32I-NEXT: lbu s10, 15(a0) -; RV32I-NEXT: lbu s11, 16(a0) -; RV32I-NEXT: lbu ra, 17(a0) -; RV32I-NEXT: lbu t4, 18(a0) -; RV32I-NEXT: lbu s0, 19(a0) +; RV32I-NEXT: lbu t1, 6(a0) +; RV32I-NEXT: lbu t2, 7(a0) +; RV32I-NEXT: lbu t3, 8(a0) +; RV32I-NEXT: lbu t4, 9(a0) +; RV32I-NEXT: lbu t5, 10(a0) +; RV32I-NEXT: lbu t6, 11(a0) +; RV32I-NEXT: lbu s0, 12(a0) +; RV32I-NEXT: lbu s2, 13(a0) +; RV32I-NEXT: lbu s4, 14(a0) +; RV32I-NEXT: lbu s5, 15(a0) +; RV32I-NEXT: lbu s6, 16(a0) +; RV32I-NEXT: lbu s7, 17(a0) +; RV32I-NEXT: lbu s8, 18(a0) +; RV32I-NEXT: lbu s9, 19(a0) ; RV32I-NEXT: slli a4, a4, 8 ; RV32I-NEXT: slli a6, a6, 16 ; RV32I-NEXT: slli a7, a7, 24 ; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: sw a3, 4(sp) # 4-byte Folded Spill ; RV32I-NEXT: or a4, a7, a6 -; RV32I-NEXT: lbu t1, 20(a0) -; RV32I-NEXT: lbu t2, 21(a0) -; RV32I-NEXT: lbu t5, 22(a0) -; RV32I-NEXT: lbu s1, 23(a0) +; RV32I-NEXT: lbu s10, 20(a0) +; RV32I-NEXT: lbu s11, 21(a0) +; RV32I-NEXT: lbu ra, 22(a0) +; RV32I-NEXT: lbu a3, 23(a0) ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: slli t3, t3, 16 +; RV32I-NEXT: slli t1, t1, 16 +; RV32I-NEXT: slli t2, t2, 24 +; RV32I-NEXT: slli t4, t4, 8 +; RV32I-NEXT: slli t5, t5, 16 ; RV32I-NEXT: slli t6, t6, 24 -; RV32I-NEXT: slli s3, s3, 8 +; RV32I-NEXT: or a5, t0, a5 +; RV32I-NEXT: or a6, t2, t1 +; RV32I-NEXT: or a7, t4, t3 +; RV32I-NEXT: or t0, t6, t5 +; RV32I-NEXT: lbu s1, 24(a0) +; RV32I-NEXT: lbu s3, 25(a0) +; RV32I-NEXT: lbu t4, 26(a0) +; RV32I-NEXT: lbu t5, 27(a0) +; RV32I-NEXT: slli s2, s2, 8 ; RV32I-NEXT: slli s4, s4, 16 ; RV32I-NEXT: slli s5, s5, 24 -; RV32I-NEXT: or a5, t0, a5 -; RV32I-NEXT: or a6, t6, t3 -; RV32I-NEXT: or a7, s3, s2 -; RV32I-NEXT: or t0, s5, s4 -; RV32I-NEXT: lbu t3, 24(a0) -; RV32I-NEXT: lbu s5, 25(a0) -; RV32I-NEXT: lbu s6, 26(a0) -; RV32I-NEXT: lbu t6, 27(a0) -; RV32I-NEXT: slli s8, s8, 8 -; RV32I-NEXT: slli s9, s9, 16 -; RV32I-NEXT: slli s10, s10, 24 -; RV32I-NEXT: slli ra, ra, 8 -; RV32I-NEXT: or s7, s8, s7 -; RV32I-NEXT: or s2, s10, s9 -; RV32I-NEXT: or s3, ra, s11 -; RV32I-NEXT: lbu s4, 28(a0) -; RV32I-NEXT: lbu s8, 29(a0) -; RV32I-NEXT: lbu s9, 30(a0) -; RV32I-NEXT: lbu s10, 31(a0) -; RV32I-NEXT: lbu a0, 0(a1) +; RV32I-NEXT: slli s7, s7, 8 +; RV32I-NEXT: or t1, s2, s0 +; RV32I-NEXT: or t2, s5, s4 +; RV32I-NEXT: or t3, s7, s6 +; RV32I-NEXT: lbu t6, 28(a0) +; RV32I-NEXT: lbu s4, 29(a0) +; RV32I-NEXT: lbu s5, 30(a0) +; RV32I-NEXT: lbu s6, 31(a0) +; RV32I-NEXT: slli s8, s8, 16 +; RV32I-NEXT: slli s9, s9, 24 +; RV32I-NEXT: slli s11, s11, 8 +; RV32I-NEXT: slli ra, ra, 16 +; RV32I-NEXT: slli a3, a3, 24 +; RV32I-NEXT: or a0, s9, s8 +; RV32I-NEXT: or s0, s11, s10 +; RV32I-NEXT: or s2, a3, ra +; RV32I-NEXT: lbu a3, 0(a1) +; RV32I-NEXT: lbu s7, 1(a1) +; RV32I-NEXT: lbu s8, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) ; RV32I-NEXT: sw zero, 24(sp) ; RV32I-NEXT: sw zero, 28(sp) ; RV32I-NEXT: sw zero, 32(sp) @@ -1995,89 +2095,88 @@ define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: sw zero, 12(sp) ; RV32I-NEXT: sw zero, 16(sp) ; RV32I-NEXT: sw zero, 20(sp) +; RV32I-NEXT: slli s3, s3, 8 +; RV32I-NEXT: or s1, s3, s1 +; RV32I-NEXT: addi s3, sp, 40 ; RV32I-NEXT: slli t4, t4, 16 -; RV32I-NEXT: slli s0, s0, 24 -; RV32I-NEXT: or t4, s0, t4 -; RV32I-NEXT: addi s0, sp, 40 -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: slli t5, t5, 16 -; RV32I-NEXT: slli s1, s1, 24 -; RV32I-NEXT: slli s5, s5, 8 -; RV32I-NEXT: slli s6, s6, 16 -; RV32I-NEXT: slli t6, t6, 24 -; RV32I-NEXT: slli s8, s8, 8 -; RV32I-NEXT: slli s9, s9, 16 -; RV32I-NEXT: slli s10, s10, 24 -; RV32I-NEXT: or t1, t2, t1 +; RV32I-NEXT: slli t5, t5, 24 +; RV32I-NEXT: slli s4, s4, 8 +; RV32I-NEXT: slli s5, s5, 16 +; RV32I-NEXT: slli s6, s6, 24 +; RV32I-NEXT: slli s7, s7, 8 +; RV32I-NEXT: slli s8, s8, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or t4, t5, t4 +; RV32I-NEXT: or t5, s4, t6 +; RV32I-NEXT: or t6, s6, s5 +; RV32I-NEXT: or a3, s7, a3 +; RV32I-NEXT: or a1, a1, s8 +; RV32I-NEXT: lw s4, 4(sp) # 4-byte Folded Reload +; RV32I-NEXT: or a4, a4, s4 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: or a6, t0, a7 +; RV32I-NEXT: or a7, t2, t1 +; RV32I-NEXT: or t0, a0, t3 +; RV32I-NEXT: or t1, s2, s0 +; RV32I-NEXT: or t2, t4, s1 +; RV32I-NEXT: or t3, t6, t5 +; RV32I-NEXT: or a0, a1, a3 +; RV32I-NEXT: sw t0, 56(sp) +; RV32I-NEXT: sw t1, 60(sp) +; RV32I-NEXT: sw t2, 64(sp) +; RV32I-NEXT: sw t3, 68(sp) +; RV32I-NEXT: sw a4, 40(sp) +; RV32I-NEXT: sw a5, 44(sp) +; RV32I-NEXT: sw a6, 48(sp) +; RV32I-NEXT: sw a7, 52(sp) ; RV32I-NEXT: srli a1, a0, 3 -; RV32I-NEXT: or t2, s1, t5 -; RV32I-NEXT: andi t5, a0, 31 -; RV32I-NEXT: or t3, s5, t3 -; RV32I-NEXT: or t6, t6, s6 -; RV32I-NEXT: or s1, s8, s4 -; RV32I-NEXT: or s4, s10, s9 -; RV32I-NEXT: andi s5, a1, 28 -; RV32I-NEXT: xori a1, t5, 31 -; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: or a4, a6, a5 -; RV32I-NEXT: or a5, t0, a7 -; RV32I-NEXT: or a6, s2, s7 -; RV32I-NEXT: or a7, t4, s3 -; RV32I-NEXT: or t0, t2, t1 -; RV32I-NEXT: or t1, t6, t3 -; RV32I-NEXT: or t2, s4, s1 -; RV32I-NEXT: sub t3, s0, s5 -; RV32I-NEXT: sw a7, 56(sp) -; RV32I-NEXT: sw t0, 60(sp) -; RV32I-NEXT: sw t1, 64(sp) -; RV32I-NEXT: sw t2, 68(sp) -; RV32I-NEXT: sw a3, 40(sp) -; RV32I-NEXT: sw a4, 44(sp) -; RV32I-NEXT: sw a5, 48(sp) -; RV32I-NEXT: sw a6, 52(sp) -; RV32I-NEXT: lw a3, 0(t3) -; RV32I-NEXT: lw a4, 4(t3) -; RV32I-NEXT: lw a5, 8(t3) -; RV32I-NEXT: lw a6, 12(t3) -; RV32I-NEXT: lw a7, 16(t3) -; RV32I-NEXT: lw t0, 20(t3) -; RV32I-NEXT: lw t1, 24(t3) -; RV32I-NEXT: lw t2, 28(t3) -; RV32I-NEXT: sll t3, a4, a0 -; RV32I-NEXT: srli t4, a3, 1 -; RV32I-NEXT: sll t5, a6, a0 -; RV32I-NEXT: srli t6, a5, 1 -; RV32I-NEXT: sll a5, a5, a0 -; RV32I-NEXT: srli a4, a4, 1 -; RV32I-NEXT: sll s0, t0, a0 -; RV32I-NEXT: srli s1, a7, 1 -; RV32I-NEXT: sll a7, a7, a0 -; RV32I-NEXT: srli a6, a6, 1 +; RV32I-NEXT: andi a3, a0, 31 +; RV32I-NEXT: andi a4, a1, 28 +; RV32I-NEXT: xori a1, a3, 31 +; RV32I-NEXT: sub a3, s3, a4 +; RV32I-NEXT: lw a4, 0(a3) +; RV32I-NEXT: lw a5, 4(a3) +; RV32I-NEXT: lw a6, 8(a3) +; RV32I-NEXT: lw a7, 12(a3) +; RV32I-NEXT: lw t0, 16(a3) +; RV32I-NEXT: lw t1, 20(a3) +; RV32I-NEXT: lw t2, 24(a3) +; RV32I-NEXT: lw a3, 28(a3) +; RV32I-NEXT: sll t3, a5, a0 +; RV32I-NEXT: srli t4, a4, 1 +; RV32I-NEXT: sll t5, a7, a0 +; RV32I-NEXT: srli t6, a6, 1 +; RV32I-NEXT: sll a6, a6, a0 +; RV32I-NEXT: srli a5, a5, 1 +; RV32I-NEXT: sll s0, t1, a0 +; RV32I-NEXT: srli s1, t0, 1 +; RV32I-NEXT: sll t0, t0, a0 +; RV32I-NEXT: srli a7, a7, 1 +; RV32I-NEXT: sll s2, a3, a0 +; RV32I-NEXT: srli a3, t2, 1 ; RV32I-NEXT: sll t2, t2, a0 -; RV32I-NEXT: srli s2, t1, 1 -; RV32I-NEXT: sll t1, t1, a0 -; RV32I-NEXT: srli t0, t0, 1 -; RV32I-NEXT: sll s3, a3, a0 +; RV32I-NEXT: srli t1, t1, 1 +; RV32I-NEXT: sll s3, a4, a0 ; RV32I-NEXT: srl a0, t4, a1 -; RV32I-NEXT: srl a3, t6, a1 -; RV32I-NEXT: srl a4, a4, a1 +; RV32I-NEXT: srl a4, t6, a1 +; RV32I-NEXT: srl a5, a5, a1 ; RV32I-NEXT: srl t4, s1, a1 -; RV32I-NEXT: srl a6, a6, a1 -; RV32I-NEXT: srl t6, s2, a1 -; RV32I-NEXT: srl t0, t0, a1 +; RV32I-NEXT: srl a7, a7, a1 +; RV32I-NEXT: srl t6, a3, a1 +; RV32I-NEXT: srl t1, t1, a1 ; RV32I-NEXT: srli s1, s3, 24 -; RV32I-NEXT: srli s2, s3, 16 -; RV32I-NEXT: srli s4, s3, 8 +; RV32I-NEXT: srli s4, s3, 16 +; RV32I-NEXT: srli s5, s3, 8 ; RV32I-NEXT: or a0, t3, a0 -; RV32I-NEXT: or a1, t5, a3 -; RV32I-NEXT: or a3, a5, a4 +; RV32I-NEXT: or a1, t5, a4 +; RV32I-NEXT: or a3, a6, a5 ; RV32I-NEXT: or a4, s0, t4 -; RV32I-NEXT: or a5, a7, a6 -; RV32I-NEXT: or a6, t2, t6 -; RV32I-NEXT: or a7, t1, t0 +; RV32I-NEXT: or a5, t0, a7 +; RV32I-NEXT: or a6, s2, t6 +; RV32I-NEXT: or a7, t2, t1 ; RV32I-NEXT: sb s3, 0(a2) -; RV32I-NEXT: sb s4, 1(a2) -; RV32I-NEXT: sb s2, 2(a2) +; RV32I-NEXT: sb s5, 1(a2) +; RV32I-NEXT: sb s4, 2(a2) ; RV32I-NEXT: sb s1, 3(a2) ; RV32I-NEXT: srli t0, a7, 24 ; RV32I-NEXT: srli t1, a7, 16 @@ -2152,17 +2251,19 @@ define void @shl_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { define void @ashr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-LABEL: ashr_32bytes: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -144 -; RV64I-NEXT: sd s0, 136(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s1, 128(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s2, 120(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s3, 112(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s4, 104(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s5, 96(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s6, 88(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s7, 80(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s8, 72(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s9, 64(sp) # 8-byte Folded Spill +; RV64I-NEXT: addi sp, sp, -160 +; RV64I-NEXT: sd s0, 152(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s1, 144(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s2, 136(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s3, 128(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s4, 120(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s5, 112(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s6, 104(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s7, 96(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s8, 88(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s9, 80(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s10, 72(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s11, 64(sp) # 8-byte Folded Spill ; RV64I-NEXT: lbu a3, 0(a0) ; RV64I-NEXT: lbu a4, 1(a0) ; RV64I-NEXT: lbu a5, 2(a0) @@ -2179,123 +2280,144 @@ define void @ashr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: lbu s1, 13(a0) ; RV64I-NEXT: lbu s2, 14(a0) ; RV64I-NEXT: lbu s3, 15(a0) -; RV64I-NEXT: slli a4, a4, 8 -; RV64I-NEXT: slli a5, a5, 16 -; RV64I-NEXT: slli a6, a6, 24 -; RV64I-NEXT: or a3, a4, a3 -; RV64I-NEXT: or a4, a6, a5 ; RV64I-NEXT: lbu s4, 16(a0) ; RV64I-NEXT: lbu s5, 17(a0) ; RV64I-NEXT: lbu s6, 18(a0) ; RV64I-NEXT: lbu s7, 19(a0) +; RV64I-NEXT: slli a4, a4, 8 +; RV64I-NEXT: slli a5, a5, 16 +; RV64I-NEXT: slli a6, a6, 24 ; RV64I-NEXT: slli t0, t0, 8 ; RV64I-NEXT: slli t1, t1, 16 ; RV64I-NEXT: slli t2, t2, 24 +; RV64I-NEXT: or a3, a4, a3 +; RV64I-NEXT: or a4, a6, a5 +; RV64I-NEXT: or a5, t0, a7 +; RV64I-NEXT: or a6, t2, t1 +; RV64I-NEXT: lbu s8, 20(a0) +; RV64I-NEXT: lbu s9, 21(a0) +; RV64I-NEXT: lbu s10, 22(a0) +; RV64I-NEXT: lbu s11, 23(a0) ; RV64I-NEXT: slli t4, t4, 8 ; RV64I-NEXT: slli t5, t5, 16 ; RV64I-NEXT: slli t6, t6, 24 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a6, t2, t1 -; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: lbu t5, 20(a0) -; RV64I-NEXT: lbu t6, 21(a0) -; RV64I-NEXT: lbu s8, 22(a0) -; RV64I-NEXT: lbu s9, 23(a0) ; RV64I-NEXT: slli s1, s1, 8 ; RV64I-NEXT: slli s2, s2, 16 ; RV64I-NEXT: slli s3, s3, 24 +; RV64I-NEXT: or a7, t4, t3 +; RV64I-NEXT: or t0, t6, t5 +; RV64I-NEXT: or t1, s1, s0 +; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: lbu t6, 24(a0) +; RV64I-NEXT: lbu s0, 25(a0) +; RV64I-NEXT: lbu s1, 26(a0) +; RV64I-NEXT: lbu s2, 27(a0) ; RV64I-NEXT: slli s5, s5, 8 ; RV64I-NEXT: slli s6, s6, 16 ; RV64I-NEXT: slli s7, s7, 24 -; RV64I-NEXT: or t1, s1, s0 -; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: slli s9, s9, 8 ; RV64I-NEXT: or t3, s5, s4 ; RV64I-NEXT: or t4, s7, s6 -; RV64I-NEXT: lbu s0, 24(a0) -; RV64I-NEXT: lbu s1, 25(a0) -; RV64I-NEXT: lbu s2, 26(a0) -; RV64I-NEXT: lbu s3, 27(a0) -; RV64I-NEXT: slli t6, t6, 8 -; RV64I-NEXT: slli s8, s8, 16 -; RV64I-NEXT: slli s9, s9, 24 -; RV64I-NEXT: slli s1, s1, 8 -; RV64I-NEXT: or t5, t6, t5 -; RV64I-NEXT: or t6, s9, s8 -; RV64I-NEXT: or s0, s1, s0 -; RV64I-NEXT: lbu s1, 28(a0) +; RV64I-NEXT: or t5, s9, s8 +; RV64I-NEXT: lbu s3, 28(a0) ; RV64I-NEXT: lbu s4, 29(a0) ; RV64I-NEXT: lbu s5, 30(a0) ; RV64I-NEXT: lbu s6, 31(a0) -; RV64I-NEXT: lbu a0, 0(a1) -; RV64I-NEXT: slli s2, s2, 16 -; RV64I-NEXT: slli s3, s3, 24 -; RV64I-NEXT: or a1, s3, s2 -; RV64I-NEXT: mv s2, sp +; RV64I-NEXT: slli s10, s10, 16 +; RV64I-NEXT: slli s11, s11, 24 +; RV64I-NEXT: slli s0, s0, 8 +; RV64I-NEXT: slli s1, s1, 16 +; RV64I-NEXT: slli s2, s2, 24 ; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or a0, s11, s10 +; RV64I-NEXT: or t6, s0, t6 +; RV64I-NEXT: or s0, s2, s1 +; RV64I-NEXT: or s1, s4, s3 +; RV64I-NEXT: lbu s2, 0(a1) +; RV64I-NEXT: lbu s3, 1(a1) +; RV64I-NEXT: lbu s4, 2(a1) +; RV64I-NEXT: lbu s7, 3(a1) ; RV64I-NEXT: slli s5, s5, 16 ; RV64I-NEXT: slli s6, s6, 24 -; RV64I-NEXT: or s1, s4, s1 -; RV64I-NEXT: srli s3, a0, 3 -; RV64I-NEXT: or s4, s6, s5 -; RV64I-NEXT: andi s5, a0, 63 -; RV64I-NEXT: andi s3, s3, 24 -; RV64I-NEXT: xori s5, s5, 63 +; RV64I-NEXT: slli s3, s3, 8 +; RV64I-NEXT: slli s4, s4, 16 +; RV64I-NEXT: slli s7, s7, 24 +; RV64I-NEXT: or s5, s6, s5 +; RV64I-NEXT: or s2, s3, s2 +; RV64I-NEXT: or s3, s7, s4 +; RV64I-NEXT: lbu s4, 5(a1) +; RV64I-NEXT: lbu s6, 4(a1) +; RV64I-NEXT: lbu s7, 6(a1) +; RV64I-NEXT: lbu a1, 7(a1) +; RV64I-NEXT: slli s4, s4, 8 +; RV64I-NEXT: or s4, s4, s6 +; RV64I-NEXT: slli s7, s7, 16 +; RV64I-NEXT: slli a1, a1, 24 +; RV64I-NEXT: or a1, a1, s7 +; RV64I-NEXT: mv s6, sp ; RV64I-NEXT: or a3, a4, a3 ; RV64I-NEXT: or a4, a6, a5 ; RV64I-NEXT: or a5, t0, a7 ; RV64I-NEXT: or a6, t2, t1 ; RV64I-NEXT: or a7, t4, t3 -; RV64I-NEXT: or t0, t6, t5 -; RV64I-NEXT: or a1, a1, s0 -; RV64I-NEXT: or t1, s4, s1 -; RV64I-NEXT: add s2, s2, s3 +; RV64I-NEXT: or a0, a0, t5 +; RV64I-NEXT: or t0, s0, t6 +; RV64I-NEXT: or t1, s5, s1 +; RV64I-NEXT: or t2, s3, s2 +; RV64I-NEXT: or a1, a1, s4 ; RV64I-NEXT: slli a4, a4, 32 ; RV64I-NEXT: slli a6, a6, 32 -; RV64I-NEXT: slli t0, t0, 32 -; RV64I-NEXT: slli t2, t1, 32 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: slli t3, t1, 32 +; RV64I-NEXT: slli a1, a1, 32 ; RV64I-NEXT: sraiw t1, t1, 31 ; RV64I-NEXT: or a3, a4, a3 ; RV64I-NEXT: or a4, a6, a5 -; RV64I-NEXT: or a5, t0, a7 -; RV64I-NEXT: or a1, t2, a1 +; RV64I-NEXT: or a0, a0, a7 +; RV64I-NEXT: or a5, t3, t0 +; RV64I-NEXT: or a1, a1, t2 ; RV64I-NEXT: sd t1, 32(sp) ; RV64I-NEXT: sd t1, 40(sp) ; RV64I-NEXT: sd t1, 48(sp) ; RV64I-NEXT: sd t1, 56(sp) ; RV64I-NEXT: sd a3, 0(sp) ; RV64I-NEXT: sd a4, 8(sp) -; RV64I-NEXT: sd a5, 16(sp) -; RV64I-NEXT: sd a1, 24(sp) -; RV64I-NEXT: ld a1, 8(s2) -; RV64I-NEXT: ld a3, 16(s2) -; RV64I-NEXT: ld a4, 0(s2) -; RV64I-NEXT: ld a5, 24(s2) -; RV64I-NEXT: srl a6, a1, a0 -; RV64I-NEXT: slli a7, a3, 1 -; RV64I-NEXT: srl a4, a4, a0 -; RV64I-NEXT: slli a1, a1, 1 -; RV64I-NEXT: srl a3, a3, a0 +; RV64I-NEXT: sd a0, 16(sp) +; RV64I-NEXT: sd a5, 24(sp) +; RV64I-NEXT: srli a0, a1, 3 +; RV64I-NEXT: andi a3, a1, 63 +; RV64I-NEXT: andi a0, a0, 24 +; RV64I-NEXT: xori a3, a3, 63 +; RV64I-NEXT: add a0, s6, a0 +; RV64I-NEXT: ld a4, 8(a0) +; RV64I-NEXT: ld a5, 16(a0) +; RV64I-NEXT: ld a6, 0(a0) +; RV64I-NEXT: ld a0, 24(a0) +; RV64I-NEXT: srl a7, a4, a1 ; RV64I-NEXT: slli t0, a5, 1 -; RV64I-NEXT: sra a5, a5, a0 -; RV64I-NEXT: sll a0, a7, s5 -; RV64I-NEXT: sll a1, a1, s5 -; RV64I-NEXT: sll a7, t0, s5 -; RV64I-NEXT: srli t0, a5, 56 -; RV64I-NEXT: srli t1, a5, 48 -; RV64I-NEXT: srli t2, a5, 40 -; RV64I-NEXT: srli t3, a5, 32 -; RV64I-NEXT: srli t4, a5, 24 -; RV64I-NEXT: srli t5, a5, 16 -; RV64I-NEXT: srli t6, a5, 8 -; RV64I-NEXT: or a0, a6, a0 -; RV64I-NEXT: or a1, a4, a1 -; RV64I-NEXT: or a3, a3, a7 +; RV64I-NEXT: srl a6, a6, a1 +; RV64I-NEXT: slli a4, a4, 1 +; RV64I-NEXT: srl a5, a5, a1 +; RV64I-NEXT: slli t1, a0, 1 +; RV64I-NEXT: sra t2, a0, a1 +; RV64I-NEXT: sll a0, t0, a3 +; RV64I-NEXT: sll a1, a4, a3 +; RV64I-NEXT: sll a3, t1, a3 +; RV64I-NEXT: srli a4, t2, 56 +; RV64I-NEXT: srli t0, t2, 48 +; RV64I-NEXT: srli t1, t2, 40 +; RV64I-NEXT: srli t3, t2, 32 +; RV64I-NEXT: srli t4, t2, 24 +; RV64I-NEXT: srli t5, t2, 16 +; RV64I-NEXT: srli t6, t2, 8 +; RV64I-NEXT: or a0, a7, a0 +; RV64I-NEXT: or a1, a6, a1 +; RV64I-NEXT: or a3, a5, a3 ; RV64I-NEXT: sb t3, 28(a2) -; RV64I-NEXT: sb t2, 29(a2) -; RV64I-NEXT: sb t1, 30(a2) -; RV64I-NEXT: sb t0, 31(a2) -; RV64I-NEXT: sb a5, 24(a2) +; RV64I-NEXT: sb t1, 29(a2) +; RV64I-NEXT: sb t0, 30(a2) +; RV64I-NEXT: sb a4, 31(a2) +; RV64I-NEXT: sb t2, 24(a2) ; RV64I-NEXT: sb t6, 25(a2) ; RV64I-NEXT: sb t5, 26(a2) ; RV64I-NEXT: sb t4, 27(a2) @@ -2316,45 +2438,47 @@ define void @ashr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV64I-NEXT: srli s3, a0, 56 ; RV64I-NEXT: srli s4, a0, 48 ; RV64I-NEXT: srli s5, a0, 40 +; RV64I-NEXT: srli s6, a0, 32 ; RV64I-NEXT: sb a7, 20(a2) ; RV64I-NEXT: sb a6, 21(a2) ; RV64I-NEXT: sb a5, 22(a2) ; RV64I-NEXT: sb a4, 23(a2) -; RV64I-NEXT: srli a4, a0, 32 +; RV64I-NEXT: srli a4, a0, 24 ; RV64I-NEXT: sb a3, 16(a2) ; RV64I-NEXT: sb t2, 17(a2) ; RV64I-NEXT: sb t1, 18(a2) ; RV64I-NEXT: sb t0, 19(a2) -; RV64I-NEXT: srli a3, a0, 24 +; RV64I-NEXT: srli a3, a0, 16 ; RV64I-NEXT: sb t6, 4(a2) ; RV64I-NEXT: sb t5, 5(a2) ; RV64I-NEXT: sb t4, 6(a2) ; RV64I-NEXT: sb t3, 7(a2) -; RV64I-NEXT: srli a5, a0, 16 +; RV64I-NEXT: srli a5, a0, 8 ; RV64I-NEXT: sb a1, 0(a2) ; RV64I-NEXT: sb s2, 1(a2) ; RV64I-NEXT: sb s1, 2(a2) ; RV64I-NEXT: sb s0, 3(a2) -; RV64I-NEXT: srli a1, a0, 8 -; RV64I-NEXT: sb a4, 12(a2) +; RV64I-NEXT: sb s6, 12(a2) ; RV64I-NEXT: sb s5, 13(a2) ; RV64I-NEXT: sb s4, 14(a2) ; RV64I-NEXT: sb s3, 15(a2) ; RV64I-NEXT: sb a0, 8(a2) -; RV64I-NEXT: sb a1, 9(a2) -; RV64I-NEXT: sb a5, 10(a2) -; RV64I-NEXT: sb a3, 11(a2) -; RV64I-NEXT: ld s0, 136(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s1, 128(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s2, 120(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s3, 112(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s4, 104(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s5, 96(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s6, 88(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s7, 80(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s8, 72(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s9, 64(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 144 +; RV64I-NEXT: sb a5, 9(a2) +; RV64I-NEXT: sb a3, 10(a2) +; RV64I-NEXT: sb a4, 11(a2) +; RV64I-NEXT: ld s0, 152(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s1, 144(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s2, 136(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s3, 128(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s4, 120(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s5, 112(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s6, 104(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s7, 96(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s8, 88(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s9, 80(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s10, 72(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s11, 64(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 160 ; RV64I-NEXT: ret ; ; RV32I-LABEL: ashr_32bytes: @@ -2379,148 +2503,159 @@ define void @ashr_32bytes(ptr %src.ptr, ptr %bitOff.ptr, ptr %dst) nounwind { ; RV32I-NEXT: lbu a7, 3(a0) ; RV32I-NEXT: lbu a5, 4(a0) ; RV32I-NEXT: lbu t0, 5(a0) -; RV32I-NEXT: lbu t3, 6(a0) -; RV32I-NEXT: lbu t4, 7(a0) -; RV32I-NEXT: lbu t6, 8(a0) -; RV32I-NEXT: lbu s0, 9(a0) -; RV32I-NEXT: lbu s4, 10(a0) -; RV32I-NEXT: lbu s5, 11(a0) -; RV32I-NEXT: lbu s6, 12(a0) -; RV32I-NEXT: lbu s7, 13(a0) -; RV32I-NEXT: lbu s8, 14(a0) -; RV32I-NEXT: lbu s9, 15(a0) -; RV32I-NEXT: lbu s10, 16(a0) -; RV32I-NEXT: lbu s11, 17(a0) -; RV32I-NEXT: lbu s2, 18(a0) -; RV32I-NEXT: lbu s3, 19(a0) +; RV32I-NEXT: lbu t1, 6(a0) +; RV32I-NEXT: lbu t2, 7(a0) +; RV32I-NEXT: lbu t3, 8(a0) +; RV32I-NEXT: lbu t4, 9(a0) +; RV32I-NEXT: lbu t5, 10(a0) +; RV32I-NEXT: lbu t6, 11(a0) +; RV32I-NEXT: lbu s0, 12(a0) +; RV32I-NEXT: lbu s1, 13(a0) +; RV32I-NEXT: lbu s2, 14(a0) +; RV32I-NEXT: lbu s3, 15(a0) +; RV32I-NEXT: lbu s4, 16(a0) +; RV32I-NEXT: lbu s5, 17(a0) +; RV32I-NEXT: lbu s6, 18(a0) +; RV32I-NEXT: lbu s7, 19(a0) ; RV32I-NEXT: slli a4, a4, 8 ; RV32I-NEXT: slli a6, a6, 16 ; RV32I-NEXT: slli a7, a7, 24 ; RV32I-NEXT: or a3, a4, a3 +; RV32I-NEXT: sw a3, 4(sp) # 4-byte Folded Spill ; RV32I-NEXT: or a4, a7, a6 -; RV32I-NEXT: lbu t1, 20(a0) -; RV32I-NEXT: lbu t2, 21(a0) -; RV32I-NEXT: lbu t5, 22(a0) -; RV32I-NEXT: lbu s1, 23(a0) +; RV32I-NEXT: lbu s8, 20(a0) +; RV32I-NEXT: lbu s9, 21(a0) +; RV32I-NEXT: lbu s10, 22(a0) +; RV32I-NEXT: lbu s11, 23(a0) ; RV32I-NEXT: slli t0, t0, 8 -; RV32I-NEXT: slli t3, t3, 16 -; RV32I-NEXT: slli t4, t4, 24 -; RV32I-NEXT: slli s0, s0, 8 -; RV32I-NEXT: slli s4, s4, 16 -; RV32I-NEXT: slli s5, s5, 24 +; RV32I-NEXT: slli t1, t1, 16 +; RV32I-NEXT: slli t2, t2, 24 +; RV32I-NEXT: slli t4, t4, 8 +; RV32I-NEXT: slli t5, t5, 16 +; RV32I-NEXT: slli t6, t6, 24 ; RV32I-NEXT: or a5, t0, a5 -; RV32I-NEXT: or a6, t4, t3 -; RV32I-NEXT: or a7, s0, t6 -; RV32I-NEXT: or t0, s5, s4 -; RV32I-NEXT: lbu t3, 24(a0) -; RV32I-NEXT: lbu s4, 25(a0) -; RV32I-NEXT: lbu s5, 26(a0) -; RV32I-NEXT: lbu ra, 27(a0) -; RV32I-NEXT: slli s7, s7, 8 -; RV32I-NEXT: slli s8, s8, 16 -; RV32I-NEXT: slli s9, s9, 24 -; RV32I-NEXT: slli s11, s11, 8 -; RV32I-NEXT: or t4, s7, s6 -; RV32I-NEXT: or t6, s9, s8 -; RV32I-NEXT: or s0, s11, s10 -; RV32I-NEXT: lbu s6, 28(a0) -; RV32I-NEXT: lbu s7, 29(a0) -; RV32I-NEXT: lbu s8, 30(a0) -; RV32I-NEXT: lbu s9, 31(a0) -; RV32I-NEXT: lbu a0, 0(a1) +; RV32I-NEXT: or a6, t2, t1 +; RV32I-NEXT: or a7, t4, t3 +; RV32I-NEXT: or t0, t6, t5 +; RV32I-NEXT: lbu ra, 24(a0) +; RV32I-NEXT: lbu a3, 25(a0) +; RV32I-NEXT: lbu t4, 26(a0) +; RV32I-NEXT: lbu t5, 27(a0) +; RV32I-NEXT: slli s1, s1, 8 ; RV32I-NEXT: slli s2, s2, 16 ; RV32I-NEXT: slli s3, s3, 24 -; RV32I-NEXT: or s2, s3, s2 -; RV32I-NEXT: addi s3, sp, 8 -; RV32I-NEXT: slli t2, t2, 8 -; RV32I-NEXT: slli t5, t5, 16 -; RV32I-NEXT: slli s1, s1, 24 -; RV32I-NEXT: slli s4, s4, 8 -; RV32I-NEXT: slli s5, s5, 16 -; RV32I-NEXT: slli ra, ra, 24 -; RV32I-NEXT: slli s7, s7, 8 -; RV32I-NEXT: slli s8, s8, 16 -; RV32I-NEXT: slli s9, s9, 24 -; RV32I-NEXT: or t1, t2, t1 -; RV32I-NEXT: srli a1, a0, 3 +; RV32I-NEXT: slli s5, s5, 8 +; RV32I-NEXT: or t1, s1, s0 +; RV32I-NEXT: or t2, s3, s2 +; RV32I-NEXT: or t3, s5, s4 +; RV32I-NEXT: lbu t6, 28(a0) +; RV32I-NEXT: lbu s0, 29(a0) +; RV32I-NEXT: lbu s1, 30(a0) +; RV32I-NEXT: lbu a0, 31(a0) +; RV32I-NEXT: slli s6, s6, 16 +; RV32I-NEXT: slli s7, s7, 24 +; RV32I-NEXT: slli s9, s9, 8 +; RV32I-NEXT: slli s10, s10, 16 +; RV32I-NEXT: slli s11, s11, 24 +; RV32I-NEXT: or s2, s7, s6 +; RV32I-NEXT: or s3, s9, s8 +; RV32I-NEXT: or s4, s11, s10 +; RV32I-NEXT: lbu s5, 0(a1) +; RV32I-NEXT: lbu s6, 1(a1) +; RV32I-NEXT: lbu s7, 2(a1) +; RV32I-NEXT: lbu a1, 3(a1) +; RV32I-NEXT: slli a3, a3, 8 +; RV32I-NEXT: or a3, a3, ra +; RV32I-NEXT: addi s8, sp, 8 +; RV32I-NEXT: slli t4, t4, 16 +; RV32I-NEXT: slli t5, t5, 24 +; RV32I-NEXT: slli s0, s0, 8 +; RV32I-NEXT: slli s1, s1, 16 +; RV32I-NEXT: slli a0, a0, 24 +; RV32I-NEXT: slli s6, s6, 8 +; RV32I-NEXT: slli s7, s7, 16 +; RV32I-NEXT: slli a1, a1, 24 +; RV32I-NEXT: or t4, t5, t4 +; RV32I-NEXT: or t5, s0, t6 +; RV32I-NEXT: or s1, a0, s1 +; RV32I-NEXT: or t6, s6, s5 +; RV32I-NEXT: or a1, a1, s7 +; RV32I-NEXT: srai s0, a0, 31 +; RV32I-NEXT: lw a0, 4(sp) # 4-byte Folded Reload +; RV32I-NEXT: or a4, a4, a0 +; RV32I-NEXT: or a5, a6, a5 +; RV32I-NEXT: or a6, t0, a7 +; RV32I-NEXT: or a7, t2, t1 +; RV32I-NEXT: or t0, s2, t3 +; RV32I-NEXT: or t1, s4, s3 +; RV32I-NEXT: or a3, t4, a3 ; RV32I-NEXT: or t2, s1, t5 -; RV32I-NEXT: andi t5, a0, 31 -; RV32I-NEXT: or t3, s4, t3 -; RV32I-NEXT: or s1, ra, s5 -; RV32I-NEXT: or s4, s7, s6 -; RV32I-NEXT: or s5, s9, s8 -; RV32I-NEXT: srai s6, s9, 31 -; RV32I-NEXT: andi s7, a1, 28 -; RV32I-NEXT: xori a1, t5, 31 -; RV32I-NEXT: or a3, a4, a3 -; RV32I-NEXT: or a4, a6, a5 -; RV32I-NEXT: or a5, t0, a7 -; RV32I-NEXT: or a6, t6, t4 -; RV32I-NEXT: or a7, s2, s0 -; RV32I-NEXT: or t0, t2, t1 -; RV32I-NEXT: or t1, s1, t3 -; RV32I-NEXT: or t2, s5, s4 -; RV32I-NEXT: sw s6, 56(sp) -; RV32I-NEXT: sw s6, 60(sp) -; RV32I-NEXT: sw s6, 64(sp) -; RV32I-NEXT: sw s6, 68(sp) -; RV32I-NEXT: sw s6, 40(sp) -; RV32I-NEXT: sw s6, 44(sp) -; RV32I-NEXT: sw s6, 48(sp) -; RV32I-NEXT: sw s6, 52(sp) -; RV32I-NEXT: add s3, s3, s7 -; RV32I-NEXT: sw a7, 24(sp) -; RV32I-NEXT: sw t0, 28(sp) -; RV32I-NEXT: sw t1, 32(sp) +; RV32I-NEXT: or a0, a1, t6 +; RV32I-NEXT: sw s0, 56(sp) +; RV32I-NEXT: sw s0, 60(sp) +; RV32I-NEXT: sw s0, 64(sp) +; RV32I-NEXT: sw s0, 68(sp) +; RV32I-NEXT: sw s0, 40(sp) +; RV32I-NEXT: sw s0, 44(sp) +; RV32I-NEXT: sw s0, 48(sp) +; RV32I-NEXT: sw s0, 52(sp) +; RV32I-NEXT: sw t0, 24(sp) +; RV32I-NEXT: sw t1, 28(sp) +; RV32I-NEXT: sw a3, 32(sp) ; RV32I-NEXT: sw t2, 36(sp) -; RV32I-NEXT: sw a3, 8(sp) -; RV32I-NEXT: sw a4, 12(sp) -; RV32I-NEXT: sw a5, 16(sp) -; RV32I-NEXT: sw a6, 20(sp) -; RV32I-NEXT: lw a3, 0(s3) -; RV32I-NEXT: lw a4, 4(s3) -; RV32I-NEXT: lw a5, 8(s3) -; RV32I-NEXT: lw a6, 12(s3) -; RV32I-NEXT: lw a7, 16(s3) -; RV32I-NEXT: lw t0, 20(s3) -; RV32I-NEXT: lw t1, 24(s3) -; RV32I-NEXT: lw t2, 28(s3) -; RV32I-NEXT: srl t3, a4, a0 -; RV32I-NEXT: slli t4, a5, 1 +; RV32I-NEXT: sw a4, 8(sp) +; RV32I-NEXT: sw a5, 12(sp) +; RV32I-NEXT: sw a6, 16(sp) +; RV32I-NEXT: sw a7, 20(sp) +; RV32I-NEXT: srli a1, a0, 3 +; RV32I-NEXT: andi a3, a0, 31 +; RV32I-NEXT: andi a4, a1, 28 +; RV32I-NEXT: xori a1, a3, 31 +; RV32I-NEXT: add a4, s8, a4 +; RV32I-NEXT: lw a3, 0(a4) +; RV32I-NEXT: lw a5, 4(a4) +; RV32I-NEXT: lw a6, 8(a4) +; RV32I-NEXT: lw a7, 12(a4) +; RV32I-NEXT: lw t0, 16(a4) +; RV32I-NEXT: lw t1, 20(a4) +; RV32I-NEXT: lw t2, 24(a4) +; RV32I-NEXT: lw a4, 28(a4) +; RV32I-NEXT: srl t3, a5, a0 +; RV32I-NEXT: slli t4, a6, 1 ; RV32I-NEXT: srl a3, a3, a0 -; RV32I-NEXT: slli a4, a4, 1 -; RV32I-NEXT: srl t5, a6, a0 -; RV32I-NEXT: slli t6, a7, 1 -; RV32I-NEXT: srl a5, a5, a0 -; RV32I-NEXT: slli a6, a6, 1 -; RV32I-NEXT: srl s0, t0, a0 -; RV32I-NEXT: slli s1, t1, 1 -; RV32I-NEXT: srl a7, a7, a0 -; RV32I-NEXT: slli t0, t0, 1 -; RV32I-NEXT: srl t1, t1, a0 -; RV32I-NEXT: slli s2, t2, 1 -; RV32I-NEXT: sra t2, t2, a0 +; RV32I-NEXT: slli a5, a5, 1 +; RV32I-NEXT: srl t5, a7, a0 +; RV32I-NEXT: slli t6, t0, 1 +; RV32I-NEXT: srl a6, a6, a0 +; RV32I-NEXT: slli a7, a7, 1 +; RV32I-NEXT: srl s0, t1, a0 +; RV32I-NEXT: slli s1, t2, 1 +; RV32I-NEXT: srl t0, t0, a0 +; RV32I-NEXT: slli t1, t1, 1 +; RV32I-NEXT: srl t2, t2, a0 +; RV32I-NEXT: slli s2, a4, 1 +; RV32I-NEXT: sra s3, a4, a0 ; RV32I-NEXT: sll a0, t4, a1 -; RV32I-NEXT: sll a4, a4, a1 -; RV32I-NEXT: sll t4, t6, a1 -; RV32I-NEXT: sll a6, a6, a1 -; RV32I-NEXT: sll t6, s1, a1 -; RV32I-NEXT: sll t0, t0, a1 -; RV32I-NEXT: sll s1, s2, a1 -; RV32I-NEXT: srli s2, t2, 24 -; RV32I-NEXT: srli s3, t2, 16 -; RV32I-NEXT: srli s4, t2, 8 +; RV32I-NEXT: sll a4, a5, a1 +; RV32I-NEXT: sll a5, t6, a1 +; RV32I-NEXT: sll a7, a7, a1 +; RV32I-NEXT: sll t4, s1, a1 +; RV32I-NEXT: sll t1, t1, a1 +; RV32I-NEXT: sll t6, s2, a1 +; RV32I-NEXT: srli s1, s3, 24 +; RV32I-NEXT: srli s2, s3, 16 +; RV32I-NEXT: srli s4, s3, 8 ; RV32I-NEXT: or a0, t3, a0 ; RV32I-NEXT: or a1, a3, a4 -; RV32I-NEXT: or a3, t5, t4 -; RV32I-NEXT: or a4, a5, a6 -; RV32I-NEXT: or a5, s0, t6 -; RV32I-NEXT: or a6, a7, t0 -; RV32I-NEXT: or a7, t1, s1 -; RV32I-NEXT: sb t2, 28(a2) +; RV32I-NEXT: or a3, t5, a5 +; RV32I-NEXT: or a4, a6, a7 +; RV32I-NEXT: or a5, s0, t4 +; RV32I-NEXT: or a6, t0, t1 +; RV32I-NEXT: or a7, t2, t6 +; RV32I-NEXT: sb s3, 28(a2) ; RV32I-NEXT: sb s4, 29(a2) -; RV32I-NEXT: sb s3, 30(a2) -; RV32I-NEXT: sb s2, 31(a2) +; RV32I-NEXT: sb s2, 30(a2) +; RV32I-NEXT: sb s1, 31(a2) ; RV32I-NEXT: srli t0, a7, 24 ; RV32I-NEXT: srli t1, a7, 16 ; RV32I-NEXT: srli t2, a7, 8 diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll index a3b4e7829a51d..6fdc63fddbc30 100644 --- a/llvm/test/CodeGen/RISCV/xqciac.ll +++ b/llvm/test/CodeGen/RISCV/xqciac.ll @@ -231,12 +231,12 @@ define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 { ; ; RV32IMXQCIAC-LABEL: pow2: ; RV32IMXQCIAC: # %bb.0: # %entry -; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: pow2: ; RV32IZBAMXQCIAC: # %bb.0: # %entry -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5 ; RV32IZBAMXQCIAC-NEXT: ret entry: %mul = mul nsw i32 %b, 32 @@ -276,12 +276,12 @@ define dso_local i32 @shladd(i32 %a, i32 %b) local_unnamed_addr #0 { ; ; RV32IMXQCIAC-LABEL: shladd: ; RV32IMXQCIAC: # %bb.0: # %entry -; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shladd: ; RV32IZBAMXQCIAC: # %bb.0: # %entry -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31 ; RV32IZBAMXQCIAC-NEXT: ret entry: %shl = shl nsw i32 %b, 31 @@ -305,9 +305,9 @@ define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 { ; RV32IMXQCIAC-LABEL: shladd64: ; RV32IMXQCIAC: # %bb.0: # %entry ; RV32IMXQCIAC-NEXT: srli a4, a2, 1 -; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31 ; RV32IMXQCIAC-NEXT: slli a2, a2, 31 -; RV32IMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31 +; RV32IMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31 ; RV32IMXQCIAC-NEXT: sltu a2, a0, a2 ; RV32IMXQCIAC-NEXT: add a1, a1, a3 ; RV32IMXQCIAC-NEXT: add a1, a1, a2 @@ -316,9 +316,9 @@ define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 { ; RV32IZBAMXQCIAC-LABEL: shladd64: ; RV32IZBAMXQCIAC: # %bb.0: # %entry ; RV32IZBAMXQCIAC-NEXT: srli a4, a2, 1 -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31 ; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 31 -; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31 ; RV32IZBAMXQCIAC-NEXT: sltu a2, a0, a2 ; RV32IZBAMXQCIAC-NEXT: add a1, a1, a3 ; RV32IZBAMXQCIAC-NEXT: add a1, a1, a2 @@ -338,12 +338,12 @@ define dso_local i32 @shladd_ordisjoint(i32 %a, i32 %b) local_unnamed_addr #0 { ; ; RV32IMXQCIAC-LABEL: shladd_ordisjoint: ; RV32IMXQCIAC: # %bb.0: # %entry -; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shladd_ordisjoint: ; RV32IZBAMXQCIAC: # %bb.0: # %entry -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22 ; RV32IZBAMXQCIAC-NEXT: ret entry: %shl = shl nsw i32 %b, 22 @@ -361,13 +361,13 @@ define dso_local i32 @shladdc1c2(i32 %a, i32 %b) local_unnamed_addr #0 { ; ; RV32IMXQCIAC-LABEL: shladdc1c2: ; RV32IMXQCIAC: # %bb.0: # %entry -; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5 ; RV32IMXQCIAC-NEXT: slli a0, a0, 26 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shladdc1c2: ; RV32IZBAMXQCIAC: # %bb.0: # %entry -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5 ; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 26 ; RV32IZBAMXQCIAC-NEXT: ret entry: @@ -388,7 +388,7 @@ define dso_local i32 @shxaddc1c2(i32 %a, i32 %b) local_unnamed_addr #0 { ; RV32IMXQCIAC-LABEL: shxaddc1c2: ; RV32IMXQCIAC: # %bb.0: # %entry ; RV32IMXQCIAC-NEXT: slli a1, a1, 28 -; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shxaddc1c2: @@ -417,18 +417,18 @@ define dso_local i64 @shladdc1c264(i64 %a, i64 %b) local_unnamed_addr #0 { ; RV32IMXQCIAC-LABEL: shladdc1c264: ; RV32IMXQCIAC: # %bb.0: # %entry ; RV32IMXQCIAC-NEXT: srli a1, a2, 12 -; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20 +; RV32IMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20 ; RV32IMXQCIAC-NEXT: slli a2, a2, 20 -; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23 +; RV32IMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23 ; RV32IMXQCIAC-NEXT: mv a0, a2 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shladdc1c264: ; RV32IZBAMXQCIAC: # %bb.0: # %entry ; RV32IZBAMXQCIAC-NEXT: srli a1, a2, 12 -; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20 ; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 20 -; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23 ; RV32IZBAMXQCIAC-NEXT: mv a0, a2 ; RV32IZBAMXQCIAC-NEXT: ret entry: @@ -449,13 +449,13 @@ define dso_local i32 @shladdc1equalc2(i32 %a, i32 %b) local_unnamed_addr #0 { ; RV32IMXQCIAC-LABEL: shladdc1equalc2: ; RV32IMXQCIAC: # %bb.0: # %entry ; RV32IMXQCIAC-NEXT: slli a1, a1, 12 -; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: shladdc1equalc2: ; RV32IZBAMXQCIAC: # %bb.0: # %entry ; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 12 -; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12 ; RV32IZBAMXQCIAC-NEXT: ret entry: %shlc1 = shl nsw i32 %a, 12 @@ -463,3 +463,30 @@ entry: %add = add nsw i32 %shlc1, %shlc2 ret i32 %add } + +define i32 @testmuliaddnegimm(i32 %a) { +; RV32IM-LABEL: testmuliaddnegimm: +; RV32IM: # %bb.0: +; RV32IM-NEXT: slli a1, a0, 1 +; RV32IM-NEXT: add a0, a1, a0 +; RV32IM-NEXT: li a1, 3 +; RV32IM-NEXT: sub a0, a1, a0 +; RV32IM-NEXT: ret +; +; RV32IMXQCIAC-LABEL: testmuliaddnegimm: +; RV32IMXQCIAC: # %bb.0: +; RV32IMXQCIAC-NEXT: li a1, 3 +; RV32IMXQCIAC-NEXT: qc.muliadd a1, a0, -3 +; RV32IMXQCIAC-NEXT: mv a0, a1 +; RV32IMXQCIAC-NEXT: ret +; +; RV32IZBAMXQCIAC-LABEL: testmuliaddnegimm: +; RV32IZBAMXQCIAC: # %bb.0: +; RV32IZBAMXQCIAC-NEXT: li a1, 3 +; RV32IZBAMXQCIAC-NEXT: qc.muliadd a1, a0, -3 +; RV32IZBAMXQCIAC-NEXT: mv a0, a1 +; RV32IZBAMXQCIAC-NEXT: ret + %mul = mul i32 %a, -3 + %add = add i32 %mul, 3 + ret i32 %add +} diff --git a/llvm/test/CodeGen/RISCV/xqcibm-cto-clo-brev.ll b/llvm/test/CodeGen/RISCV/xqcibm-cto-clo-brev.ll index f227fa9aa423d..2fa06517508ce 100644 --- a/llvm/test/CodeGen/RISCV/xqcibm-cto-clo-brev.ll +++ b/llvm/test/CodeGen/RISCV/xqcibm-cto-clo-brev.ll @@ -105,6 +105,7 @@ define i16 @test_cttz_i16(i16 %a) nounwind { ; ; RV32ZBBXQCIBM-LABEL: test_cttz_i16: ; RV32ZBBXQCIBM: # %bb.0: +; RV32ZBBXQCIBM-NEXT: not a0, a0 ; RV32ZBBXQCIBM-NEXT: qc.insbi a0, -1, 1, 16 ; RV32ZBBXQCIBM-NEXT: ctz a0, a0 ; RV32ZBBXQCIBM-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/xqcibm-insert.ll b/llvm/test/CodeGen/RISCV/xqcibm-insert.ll index 6b7f9ae856625..88054a691bad1 100644 --- a/llvm/test/CodeGen/RISCV/xqcibm-insert.ll +++ b/llvm/test/CodeGen/RISCV/xqcibm-insert.ll @@ -47,6 +47,29 @@ define i32 @test_insbi_mask(i32 %a) nounwind { ret i32 %or } +define i32 @test_insbi_mask_mv(i32 %a, i32 %b) nounwind { +; RV32I-LABEL: test_insbi_mask_mv: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, 16 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: ret +; +; RV32IXQCIBM-LABEL: test_insbi_mask_mv: +; RV32IXQCIBM: # %bb.0: +; RV32IXQCIBM-NEXT: mv a0, a1 +; RV32IXQCIBM-NEXT: qc.insbi a0, -1, 16, 0 +; RV32IXQCIBM-NEXT: ret +; +; RV32IXQCIBMZBS-LABEL: test_insbi_mask_mv: +; RV32IXQCIBMZBS: # %bb.0: +; RV32IXQCIBMZBS-NEXT: mv a0, a1 +; RV32IXQCIBMZBS-NEXT: qc.insbi a0, -1, 16, 0 +; RV32IXQCIBMZBS-NEXT: ret + %or = or i32 %b, 65535 + ret i32 %or +} + define i32 @test_insbi_shifted_mask(i32 %a) nounwind { ; RV32I-LABEL: test_insbi_shifted_mask: ; RV32I: # %bb.0: @@ -67,6 +90,36 @@ define i32 @test_insbi_shifted_mask(i32 %a) nounwind { ret i32 %or } +define i32 @test_insbi_shifted_mask_multiple_uses(i32 %a) nounwind { +; RV32I-LABEL: test_insbi_shifted_mask_multiple_uses: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a1, 15 +; RV32I-NEXT: or a1, a0, a1 +; RV32I-NEXT: addi a0, a0, 10 +; RV32I-NEXT: xor a0, a1, a0 +; RV32I-NEXT: ret +; +; RV32IXQCIBM-LABEL: test_insbi_shifted_mask_multiple_uses: +; RV32IXQCIBM: # %bb.0: +; RV32IXQCIBM-NEXT: lui a1, 15 +; RV32IXQCIBM-NEXT: or a1, a1, a0 +; RV32IXQCIBM-NEXT: addi a0, a0, 10 +; RV32IXQCIBM-NEXT: xor a0, a0, a1 +; RV32IXQCIBM-NEXT: ret +; +; RV32IXQCIBMZBS-LABEL: test_insbi_shifted_mask_multiple_uses: +; RV32IXQCIBMZBS: # %bb.0: +; RV32IXQCIBMZBS-NEXT: lui a1, 15 +; RV32IXQCIBMZBS-NEXT: or a1, a1, a0 +; RV32IXQCIBMZBS-NEXT: addi a0, a0, 10 +; RV32IXQCIBMZBS-NEXT: xor a0, a0, a1 +; RV32IXQCIBMZBS-NEXT: ret + %or = or i32 %a, 61440 + %add = add i32 %a, 10 + %xor = xor i32 %or, %add + ret i32 %xor +} + define i32 @test_single_bit_set(i32 %a) nounwind { ; RV32I-LABEL: test_single_bit_set: ; RV32I: # %bb.0: diff --git a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll index 9ccd4f1c0ac9a..767ef7eb510e6 100644 --- a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll +++ b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll @@ -184,4 +184,29 @@ entry: ret i32 %2 } +define i32 @test_generic_inst(i32 %arg) #0 { +;CHECK-LABEL: test_generic_inst: +;CHECK: ! fake_use: {{.*}} +;CHECK: bne {{.*}} +;CHECK-NEXT: nop + %bar1 = call i32 @bar(i32 %arg) + %even = and i32 %bar1, 1 + %cmp = icmp eq i32 %even, 0 + ; This shouldn't get reordered into a delay slot + call void (...) @llvm.fake.use(i32 %arg) + br i1 %cmp, label %true, label %false +true: + %bar2 = call i32 @bar(i32 %bar1) + br label %cont + +false: + %inc = add nsw i32 %bar1, 1 + br label %cont + +cont: + %ret = phi i32 [ %bar2, %true ], [ %inc, %false ] + ret i32 %ret +} + +declare void @llvm.fake.use(...) attributes #0 = { nounwind "disable-tail-calls"="true" } diff --git a/llvm/test/CodeGen/SPARC/64abi.ll b/llvm/test/CodeGen/SPARC/64abi.ll index 6485a7f13e8d5..dc8c9af4a5185 100644 --- a/llvm/test/CodeGen/SPARC/64abi.ll +++ b/llvm/test/CodeGen/SPARC/64abi.ll @@ -473,8 +473,8 @@ declare i64 @receive_fp128(i64 %a, ...) ; HARD-DAG: ldx [%sp+[[Offset0]]], %o2 ; HARD-DAG: ldx [%sp+[[Offset1]]], %o3 ; SOFT-DAG: mov %i0, %o0 -; SOFT-DAG: mov %i1, %o1 ; SOFT-DAG: mov %i2, %o2 +; SOFT-DAG: mov %i3, %o3 ; CHECK: call receive_fp128 define i64 @test_fp128_variable_args(i64 %a, fp128 %b) { entry: @@ -482,6 +482,19 @@ entry: ret i64 %0 } +declare i64 @receive_i128(i64 %a, i128 %b) + +; CHECK-LABEL: test_i128_args: +; CHECK: mov %i3, %o3 +; CHECK: mov %i2, %o2 +; CHECK: mov %i0, %o0 +; CHECK: call receive_i128 +define i64 @test_i128_args(i64 %a, i128 %b) { +entry: + %0 = call i64 @receive_i128(i64 %a, i128 %b) + ret i64 %0 +} + ; CHECK-LABEL: test_call_libfunc: ; HARD: st %f1, [%fp+[[Offset0:[0-9]+]]] ; HARD: fmovs %f3, %f1 diff --git a/llvm/test/CodeGen/SPARC/float-ua2007.ll b/llvm/test/CodeGen/SPARC/float-ua2007.ll new file mode 100644 index 0000000000000..252b47943fe43 --- /dev/null +++ b/llvm/test/CodeGen/SPARC/float-ua2007.ll @@ -0,0 +1,275 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=sparc64 --fp-contract=fast -mattr=-ua2007 < %s | FileCheck %s -check-prefix=NO-UA2007 +; RUN: llc -mtriple=sparc64 --fp-contract=fast -mattr=+ua2007 < %s | FileCheck %s -check-prefix=UA2007 + +define float @fmadds(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: fmadds: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fadds %f0, %f5, %f0 +; +; UA2007-LABEL: fmadds: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmadds %f1, %f3, %f5, %f0 + %ret = call float @llvm.fmuladd.f32(float %a, float %b, float %c) + ret float %ret +} + +define double @fmaddd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: fmaddd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: faddd %f0, %f4, %f0 +; +; UA2007-LABEL: fmaddd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmaddd %f0, %f2, %f4, %f0 + %ret = call double @llvm.fmuladd.f64(double %a, double %b, double %c) + ret double %ret +} + +define float @fmsubs(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: fmsubs: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fsubs %f0, %f5, %f0 +; +; UA2007-LABEL: fmsubs: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmsubs %f1, %f3, %f5, %f0 + %neg = fneg float %c + %ret = call float @llvm.fmuladd.f32(float %a, float %b, float %neg) + ret float %ret +} + +define double @fmsubd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: fmsubd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fsubd %f0, %f4, %f0 +; +; UA2007-LABEL: fmsubd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmsubd %f0, %f2, %f4, %f0 + %neg = fneg double %c + %ret = call double @llvm.fmuladd.f64(double %a, double %b, double %neg) + ret double %ret +} + +define float @fnmadds(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: fnmadds: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: fadds %f0, %f5, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegs %f0, %f0 +; +; UA2007-LABEL: fnmadds: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmadds %f1, %f3, %f5, %f0 + %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %c) + %ret = fneg float %fma + ret float %ret +} + +define double @fnmaddd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: fnmaddd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: faddd %f0, %f4, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegd %f0, %f0 +; +; UA2007-LABEL: fnmaddd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmaddd %f0, %f2, %f4, %f0 + %fma = call double @llvm.fmuladd.f64(double %a, double %b, double %c) + %ret = fneg double %fma + ret double %ret +} + +define float @fnmsubs(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: fnmsubs: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: fsubs %f0, %f5, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegs %f0, %f0 +; +; UA2007-LABEL: fnmsubs: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmsubs %f1, %f3, %f5, %f0 + %neg = fneg float %c + %fma = call float @llvm.fmuladd.f32(float %a, float %b, float %neg) + %ret = fneg float %fma + ret float %ret +} + +define double @fnmsubd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: fnmsubd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: fsubd %f0, %f4, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegd %f0, %f0 +; +; UA2007-LABEL: fnmsubd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmsubd %f0, %f2, %f4, %f0 + %neg = fneg double %c + %fma = call double @llvm.fmuladd.f64(double %a, double %b, double %neg) + %ret = fneg double %fma + ret double %ret +} + + +define float @combine_madds(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: combine_madds: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fadds %f0, %f5, %f0 +; +; UA2007-LABEL: combine_madds: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmadds %f1, %f3, %f5, %f0 + %mul = fmul float %a, %b + %add = fadd float %mul, %c + ret float %add +} + +define double @combine_maddd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: combine_maddd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: faddd %f0, %f4, %f0 +; +; UA2007-LABEL: combine_maddd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmaddd %f0, %f2, %f4, %f0 + %mul = fmul double %a, %b + %add = fadd double %mul, %c + ret double %add +} + +define float @combine_msubs(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: combine_msubs: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fsubs %f0, %f5, %f0 +; +; UA2007-LABEL: combine_msubs: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmsubs %f1, %f3, %f5, %f0 + %mul = fmul float %a, %b + %sub = fsub float %mul, %c + ret float %sub +} + +define double @combine_msubd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: combine_msubd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fsubd %f0, %f4, %f0 +; +; UA2007-LABEL: combine_msubd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fmsubd %f0, %f2, %f4, %f0 + %mul = fmul double %a, %b + %sub = fsub double %mul, %c + ret double %sub +} + +define float @combine_nmadds(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: combine_nmadds: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: fadds %f0, %f5, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegs %f0, %f0 +; +; UA2007-LABEL: combine_nmadds: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmadds %f1, %f3, %f5, %f0 + %mul = fmul float %a, %b + %add = fadd float %mul, %c + %neg = fneg float %add + ret float %neg +} + +define double @combine_nmaddd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: combine_nmaddd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: faddd %f0, %f4, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegd %f0, %f0 +; +; UA2007-LABEL: combine_nmaddd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmaddd %f0, %f2, %f4, %f0 + %mul = fmul double %a, %b + %add = fadd double %mul, %c + %neg = fneg double %add + ret double %neg +} + +define float @combine_nmsubs(float %a, float %b, float %c) nounwind { +; NO-UA2007-LABEL: combine_nmsubs: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuls %f1, %f3, %f0 +; NO-UA2007-NEXT: fsubs %f0, %f5, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegs %f0, %f0 +; +; UA2007-LABEL: combine_nmsubs: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmsubs %f1, %f3, %f5, %f0 + %mul = fmul float %a, %b + %sub = fsub float %mul, %c + %neg = fneg float %sub + ret float %neg +} + +define double @combine_nmsubd(double %a, double %b, double %c) nounwind { +; NO-UA2007-LABEL: combine_nmsubd: +; NO-UA2007: ! %bb.0: +; NO-UA2007-NEXT: fmuld %f0, %f2, %f0 +; NO-UA2007-NEXT: fsubd %f0, %f4, %f0 +; NO-UA2007-NEXT: retl +; NO-UA2007-NEXT: fnegd %f0, %f0 +; +; UA2007-LABEL: combine_nmsubd: +; UA2007: ! %bb.0: +; UA2007-NEXT: retl +; UA2007-NEXT: fnmsubd %f0, %f2, %f4, %f0 + %mul = fmul double %a, %b + %sub = fsub double %mul, %c + %neg = fneg double %sub + ret double %neg +} + +declare float @llvm.fmuladd.f32(float, float, float) +declare double @llvm.fmuladd.f64(double, double, double) diff --git a/llvm/test/CodeGen/SPARC/tls-sp.ll b/llvm/test/CodeGen/SPARC/tls-sp.ll new file mode 100644 index 0000000000000..de9af01398d23 --- /dev/null +++ b/llvm/test/CodeGen/SPARC/tls-sp.ll @@ -0,0 +1,105 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=sparc -relocation-model=pic < %s | FileCheck --check-prefix=SPARC %s +; RUN: llc -mtriple=sparc64 -relocation-model=pic < %s | FileCheck --check-prefix=SPARC64 %s + +@x = external thread_local global i8 + +;; Test that we don't over-allocate stack space when calling __tls_get_addr +;; with the call frame pseudos able to be eliminated. +define ptr @no_alloca() nounwind { +; SPARC-LABEL: no_alloca: +; SPARC: ! %bb.0: ! %entry +; SPARC-NEXT: save %sp, -96, %sp +; SPARC-NEXT: .Ltmp0: +; SPARC-NEXT: call .Ltmp1 +; SPARC-NEXT: .Ltmp2: +; SPARC-NEXT: sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.Ltmp0)), %i0 +; SPARC-NEXT: .Ltmp1: +; SPARC-NEXT: or %i0, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.Ltmp0)), %i0 +; SPARC-NEXT: add %i0, %o7, %i0 +; SPARC-NEXT: sethi %tgd_hi22(x), %i1 +; SPARC-NEXT: add %i1, %tgd_lo10(x), %i1 +; SPARC-NEXT: add %i0, %i1, %o0, %tgd_add(x) +; SPARC-NEXT: call __tls_get_addr, %tgd_call(x) +; SPARC-NEXT: nop +; SPARC-NEXT: ret +; SPARC-NEXT: restore %g0, %o0, %o0 +; +; SPARC64-LABEL: no_alloca: +; SPARC64: ! %bb.0: ! %entry +; SPARC64-NEXT: save %sp, -128, %sp +; SPARC64-NEXT: .Ltmp0: +; SPARC64-NEXT: rd %pc, %o7 +; SPARC64-NEXT: .Ltmp2: +; SPARC64-NEXT: sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.Ltmp0)), %i0 +; SPARC64-NEXT: .Ltmp1: +; SPARC64-NEXT: or %i0, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.Ltmp0)), %i0 +; SPARC64-NEXT: add %i0, %o7, %i0 +; SPARC64-NEXT: sethi %tgd_hi22(x), %i1 +; SPARC64-NEXT: add %i1, %tgd_lo10(x), %i1 +; SPARC64-NEXT: add %i0, %i1, %o0, %tgd_add(x) +; SPARC64-NEXT: call __tls_get_addr, %tgd_call(x) +; SPARC64-NEXT: nop +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore %g0, %o0, %o0 +entry: + %0 = call ptr @llvm.threadlocal.address.p0(ptr @x) + ret ptr %0 +} + +;; Test that %sp is valid for the call to __tls_get_addr. We store to a dynamic +;; alloca in order to prevent eliminating any call frame pseudos from the call. +define ptr @dynamic_alloca(i64 %n) nounwind { +; SPARC-LABEL: dynamic_alloca: +; SPARC: ! %bb.0: ! %entry +; SPARC-NEXT: save %sp, -96, %sp +; SPARC-NEXT: .Ltmp3: +; SPARC-NEXT: call .Ltmp4 +; SPARC-NEXT: .Ltmp5: +; SPARC-NEXT: sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp3)), %i0 +; SPARC-NEXT: .Ltmp4: +; SPARC-NEXT: or %i0, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp4-.Ltmp3)), %i0 +; SPARC-NEXT: add %i0, %o7, %i0 +; SPARC-NEXT: sethi %tgd_hi22(x), %i2 +; SPARC-NEXT: add %i2, %tgd_lo10(x), %i2 +; SPARC-NEXT: add %i0, %i2, %o0, %tgd_add(x) +; SPARC-NEXT: call __tls_get_addr, %tgd_call(x) +; SPARC-NEXT: nop +; SPARC-NEXT: add %i1, 7, %i0 +; SPARC-NEXT: and %i0, -8, %i0 +; SPARC-NEXT: sub %sp, %i0, %i0 +; SPARC-NEXT: add %i0, -8, %sp +; SPARC-NEXT: mov 1, %i1 +; SPARC-NEXT: stb %i1, [%i0+88] +; SPARC-NEXT: ret +; SPARC-NEXT: restore %g0, %o0, %o0 +; +; SPARC64-LABEL: dynamic_alloca: +; SPARC64: ! %bb.0: ! %entry +; SPARC64-NEXT: save %sp, -128, %sp +; SPARC64-NEXT: .Ltmp3: +; SPARC64-NEXT: rd %pc, %o7 +; SPARC64-NEXT: .Ltmp5: +; SPARC64-NEXT: sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp3)), %i1 +; SPARC64-NEXT: .Ltmp4: +; SPARC64-NEXT: or %i1, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp4-.Ltmp3)), %i1 +; SPARC64-NEXT: add %i1, %o7, %i1 +; SPARC64-NEXT: sethi %tgd_hi22(x), %i2 +; SPARC64-NEXT: add %i2, %tgd_lo10(x), %i2 +; SPARC64-NEXT: add %i1, %i2, %o0, %tgd_add(x) +; SPARC64-NEXT: call __tls_get_addr, %tgd_call(x) +; SPARC64-NEXT: nop +; SPARC64-NEXT: add %i0, 15, %i0 +; SPARC64-NEXT: and %i0, -16, %i0 +; SPARC64-NEXT: sub %sp, %i0, %i0 +; SPARC64-NEXT: mov %i0, %sp +; SPARC64-NEXT: mov 1, %i1 +; SPARC64-NEXT: stb %i1, [%i0+2175] +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore %g0, %o0, %o0 +entry: + %0 = call ptr @llvm.threadlocal.address.p0(ptr @x) + %1 = alloca i8, i64 %n + store i8 1, ptr %1 + ret ptr %0 +} diff --git a/llvm/test/CodeGen/SystemZ/pr60413.ll b/llvm/test/CodeGen/SystemZ/pr60413.ll index bbf4d50bd716d..8a6a30318ae58 100644 --- a/llvm/test/CodeGen/SystemZ/pr60413.ll +++ b/llvm/test/CodeGen/SystemZ/pr60413.ll @@ -16,31 +16,31 @@ define dso_local void @m() local_unnamed_addr #1 { ; CHECK-NEXT: stmg %r13, %r15, 104(%r15) ; CHECK-NEXT: aghi %r15, -168 ; CHECK-NEXT: lhrl %r1, f+4 +; CHECK-NEXT: sll %r1, 8 ; CHECK-NEXT: larl %r2, f -; CHECK-NEXT: llc %r2, 6(%r2) -; CHECK-NEXT: larl %r3, e -; CHECK-NEXT: lb %r0, 3(%r3) -; CHECK-NEXT: rosbg %r2, %r1, 32, 55, 8 -; CHECK-NEXT: vlvgp %v0, %r2, %r0 -; CHECK-NEXT: vlvgf %v0, %r2, 0 -; CHECK-NEXT: vlvgf %v0, %r2, 2 -; CHECK-NEXT: vlvgp %v1, %r0, %r2 -; CHECK-NEXT: vlvgp %v2, %r2, %r2 -; CHECK-NEXT: lr %r1, %r2 +; CHECK-NEXT: ic %r1, 6(%r2) +; CHECK-NEXT: larl %r2, e +; CHECK-NEXT: lb %r0, 3(%r2) +; CHECK-NEXT: vlvgp %v0, %r0, %r1 +; CHECK-NEXT: vlvgp %v1, %r1, %r0 +; CHECK-NEXT: vlvgf %v1, %r1, 0 +; CHECK-NEXT: vlvgf %v1, %r1, 2 +; CHECK-NEXT: vlvgp %v2, %r1, %r1 +; CHECK-NEXT: # kill: def $r1l killed $r1l killed $r1d ; CHECK-NEXT: nilh %r1, 255 ; CHECK-NEXT: chi %r1, 128 ; CHECK-NEXT: ipm %r1 ; CHECK-NEXT: risbg %r1, %r1, 63, 191, 36 +; CHECK-NEXT: vlvgf %v0, %r0, 0 +; CHECK-NEXT: vlvgf %v0, %r0, 2 ; CHECK-NEXT: vgbm %v3, 30583 ; CHECK-NEXT: vn %v0, %v0, %v3 -; CHECK-NEXT: vlvgf %v1, %r0, 0 -; CHECK-NEXT: vlvgf %v1, %r0, 2 ; CHECK-NEXT: vn %v1, %v1, %v3 ; CHECK-NEXT: vrepf %v2, %v2, 1 ; CHECK-NEXT: vn %v2, %v2, %v3 ; CHECK-NEXT: vrepif %v3, 127 -; CHECK-NEXT: vchlf %v0, %v0, %v3 -; CHECK-NEXT: vlgvf %r13, %v0, 0 +; CHECK-NEXT: vchlf %v1, %v1, %v3 +; CHECK-NEXT: vlgvf %r13, %v1, 0 ; CHECK-NEXT: vchlf %v2, %v2, %v3 ; CHECK-NEXT: vlgvf %r3, %v2, 1 ; CHECK-NEXT: nilf %r3, 1 @@ -54,13 +54,13 @@ define dso_local void @m() local_unnamed_addr #1 { ; CHECK-NEXT: nilf %r14, 1 ; CHECK-NEXT: rosbg %r2, %r14, 32, 51, 12 ; CHECK-NEXT: rosbg %r2, %r13, 52, 52, 11 -; CHECK-NEXT: vlgvf %r13, %v0, 1 +; CHECK-NEXT: vlgvf %r13, %v1, 1 ; CHECK-NEXT: rosbg %r2, %r13, 53, 53, 10 -; CHECK-NEXT: vlgvf %r13, %v0, 2 +; CHECK-NEXT: vlgvf %r13, %v1, 2 ; CHECK-NEXT: rosbg %r2, %r13, 54, 54, 9 -; CHECK-NEXT: vlgvf %r13, %v0, 3 +; CHECK-NEXT: vlgvf %r13, %v1, 3 ; CHECK-NEXT: rosbg %r2, %r13, 55, 55, 8 -; CHECK-NEXT: vchlf %v0, %v1, %v3 +; CHECK-NEXT: vchlf %v0, %v0, %v3 ; CHECK-NEXT: vlgvf %r13, %v0, 0 ; CHECK-NEXT: rosbg %r2, %r13, 56, 56, 7 ; CHECK-NEXT: vlgvf %r13, %v0, 1 diff --git a/llvm/test/CodeGen/WebAssembly/fake-use.ll b/llvm/test/CodeGen/WebAssembly/fake-use.ll new file mode 100644 index 0000000000000..a18ce33566df0 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/fake-use.ll @@ -0,0 +1,25 @@ +; RUN: llc < %s | llvm-mc -triple=wasm32-unknown-unknown + +target triple = "wasm32-unknown-unknown" + +define void @fake_use() { + %t = call i32 @foo() + tail call void (...) @llvm.fake.use(i32 %t) + ret void +} + +; %t shouldn't be converted to TEE in RegStackify, because the FAKE_USE will be +; deleted in the beginning of ExplicitLocals. +define void @fake_use_no_tee() { + %t = call i32 @foo() + tail call void (...) @llvm.fake.use(i32 %t) + call void @use(i32 %t) + ret void +} + +declare i32 @foo() +declare void @use(i32 %t) +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) +declare void @llvm.fake.use(...) #0 + +attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } diff --git a/llvm/test/CodeGen/WebAssembly/removed-terminator.ll b/llvm/test/CodeGen/WebAssembly/removed-terminator.ll new file mode 100644 index 0000000000000..188f6f67eee8b --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/removed-terminator.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -O0 -verify-machineinstrs < %s | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define void @test(i1 %x) { +; CHECK-LABEL: test: +; CHECK: .functype test (i32) -> () +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: i32.const -1 +; CHECK-NEXT: i32.xor +; CHECK-NEXT: i32.const 1 +; CHECK-NEXT: i32.and +; CHECK-NEXT: drop +; CHECK-NEXT: # %bb.1: # %exit +; CHECK-NEXT: return + %y = xor i1 %x, true + ; This br_if's operand (%y) is stackified in RegStackify. But this terminator + ; will be removed in CFGSort after that. We need to make sure we unstackify %y + ; so that it can be dropped in ExplicitLocals. + br i1 %y, label %exit, label %exit + +exit: + ret void +} diff --git a/llvm/test/CodeGen/X86/abds-neg.ll b/llvm/test/CodeGen/X86/abds-neg.ll index f6d66ab47ce05..d9064c684cb20 100644 --- a/llvm/test/CodeGen/X86/abds-neg.ll +++ b/llvm/test/CodeGen/X86/abds-neg.ll @@ -367,44 +367,49 @@ define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: subl %ecx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %edx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: sbbl %edi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %esi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll %eax, %esi -; X86-NEXT: cmovll %ebx, %edi -; X86-NEXT: cmovll %ebp, %edx -; X86-NEXT: cmovll (%esp), %ecx # 4-byte Folded Reload -; X86-NEXT: xorl %ebx, %ebx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %edx +; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %edx +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: sbbl %edx, %ebx +; X86-NEXT: movl 52(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %eax +; X86-NEXT: sbbl 32(%ebp), %edx +; X86-NEXT: sbbl 36(%ebp), %esi +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %ebx, %edx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: xorl %edi, %edi ; X86-NEXT: negl %ecx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %edx, %ebp -; X86-NEXT: movl $0, %edx -; X86-NEXT: sbbl %edi, %edx -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %edx, 8(%eax) -; X86-NEXT: movl %ebx, 12(%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %eax, %ebx +; X86-NEXT: movl $0, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 8(%ebp), %edx +; X86-NEXT: movl %ecx, (%edx) +; X86-NEXT: movl %ebx, 4(%edx) +; X86-NEXT: movl %eax, 8(%edx) +; X86-NEXT: movl %edi, 12(%edx) +; X86-NEXT: movl %edx, %eax +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -438,44 +443,49 @@ define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: subl %ecx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %edx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: sbbl %edi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %esi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll %eax, %esi -; X86-NEXT: cmovll %ebx, %edi -; X86-NEXT: cmovll %ebp, %edx -; X86-NEXT: cmovll (%esp), %ecx # 4-byte Folded Reload -; X86-NEXT: xorl %ebx, %ebx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %edx +; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %edx +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: sbbl %edx, %ebx +; X86-NEXT: movl 52(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %eax +; X86-NEXT: sbbl 32(%ebp), %edx +; X86-NEXT: sbbl 36(%ebp), %esi +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %ebx, %edx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: xorl %edi, %edi ; X86-NEXT: negl %ecx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %edx, %ebp -; X86-NEXT: movl $0, %edx -; X86-NEXT: sbbl %edi, %edx -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %edx, 8(%eax) -; X86-NEXT: movl %ebx, 12(%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %eax, %ebx +; X86-NEXT: movl $0, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 8(%ebp), %edx +; X86-NEXT: movl %ecx, (%edx) +; X86-NEXT: movl %ebx, 4(%edx) +; X86-NEXT: movl %eax, 8(%edx) +; X86-NEXT: movl %edi, 12(%edx) +; X86-NEXT: movl %edx, %eax +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -639,55 +649,59 @@ define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_minmax_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: cmpl %eax, %esi -; X86-NEXT: sbbl %ebx, %ecx -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: sbbl %ebp, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: sbbl %edi, %ecx -; X86-NEXT: movl %edi, %ecx -; X86-NEXT: cmovll %edx, %ecx -; X86-NEXT: movl %ecx, (%esp) # 4-byte Spill -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl %ebx, %ecx -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %eax, %edx -; X86-NEXT: cmovll %esi, %edx -; X86-NEXT: cmpl %esi, %eax -; X86-NEXT: movl %ebx, %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl %edi, %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %ebx -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %eax -; X86-NEXT: subl %eax, %edx -; X86-NEXT: sbbl %ebx, %ecx -; X86-NEXT: sbbl %esi, %ebp -; X86-NEXT: movl (%esp), %esi # 4-byte Reload -; X86-NEXT: sbbl %edi, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: movl %ecx, 4(%eax) -; X86-NEXT: movl %ebp, 8(%eax) -; X86-NEXT: movl %esi, 12(%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %esi +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: cmpl %esi, %edi +; X86-NEXT: sbbl 44(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: movl %ebx, %eax +; X86-NEXT: cmovll %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %edx, %eax +; X86-NEXT: cmovll 32(%ebp), %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: cmovll 28(%ebp), %eax +; X86-NEXT: movl %esi, %ecx +; X86-NEXT: cmovll %edi, %ecx +; X86-NEXT: cmpl %edi, %esi +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: sbbl 28(%ebp), %edi +; X86-NEXT: movl %edx, %edi +; X86-NEXT: sbbl 32(%ebp), %edi +; X86-NEXT: movl %ebx, %edi +; X86-NEXT: sbbl 36(%ebp), %edi +; X86-NEXT: cmovll 36(%ebp), %ebx +; X86-NEXT: cmovll 32(%ebp), %edx +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: cmovll 28(%ebp), %edi +; X86-NEXT: cmovll 24(%ebp), %esi +; X86-NEXT: subl %esi, %ecx +; X86-NEXT: sbbl %edi, %eax +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload +; X86-NEXT: sbbl %edx, %edi +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload +; X86-NEXT: sbbl %ebx, %esi +; X86-NEXT: movl 8(%ebp), %edx +; X86-NEXT: movl %ecx, (%edx) +; X86-NEXT: movl %eax, 4(%edx) +; X86-NEXT: movl %edi, 8(%edx) +; X86-NEXT: movl %esi, 12(%edx) +; X86-NEXT: movl %edx, %eax +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -848,37 +862,41 @@ define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_cmp_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovgel (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovgel %ebx, %esi -; X86-NEXT: cmovgel %ebp, %ecx -; X86-NEXT: cmovgel %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %edx +; X86-NEXT: movl 40(%ebp), %eax +; X86-NEXT: movl 44(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 48(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 36(%ebp), %ebx +; X86-NEXT: movl 52(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 40(%ebp), %ecx +; X86-NEXT: sbbl 44(%ebp), %edx +; X86-NEXT: sbbl 48(%ebp), %esi +; X86-NEXT: sbbl 52(%ebp), %ebx +; X86-NEXT: cmovgel {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovgel {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovgel %edi, %esi +; X86-NEXT: cmovgel %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -1058,15 +1076,15 @@ define i64 @abd_subnsw_i64(i64 %a, i64 %b) nounwind { ; X86-NEXT: pushl %esi ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %edx +; X86-NEXT: subl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, %edx ; X86-NEXT: sarl $31, %edx -; X86-NEXT: xorl %edx, %ecx ; X86-NEXT: xorl %edx, %esi +; X86-NEXT: xorl %edx, %ecx ; X86-NEXT: movl %edx, %eax -; X86-NEXT: subl %esi, %eax -; X86-NEXT: sbbl %ecx, %edx +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: sbbl %esi, %edx ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -1089,15 +1107,15 @@ define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind { ; X86-NEXT: pushl %esi ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %edx +; X86-NEXT: subl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, %edx ; X86-NEXT: sarl $31, %edx -; X86-NEXT: xorl %edx, %ecx ; X86-NEXT: xorl %edx, %esi +; X86-NEXT: xorl %edx, %ecx ; X86-NEXT: movl %edx, %eax -; X86-NEXT: subl %esi, %eax -; X86-NEXT: sbbl %ecx, %edx +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: sbbl %esi, %edx ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -1118,35 +1136,39 @@ define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_subnsw_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: movl %ebx, %ebp -; X86-NEXT: subl %edi, %ebp -; X86-NEXT: movl %ebx, %edi -; X86-NEXT: sbbl %esi, %edi -; X86-NEXT: movl %ebx, %esi -; X86-NEXT: sbbl %edx, %esi -; X86-NEXT: sbbl %ecx, %ebx -; X86-NEXT: movl %ebp, (%eax) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %edx +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %edx +; X86-NEXT: sbbl 48(%ebp), %ecx +; X86-NEXT: sbbl 52(%ebp), %eax +; X86-NEXT: movl %eax, %esi +; X86-NEXT: sarl $31, %esi +; X86-NEXT: xorl %esi, %eax +; X86-NEXT: xorl %esi, %ecx +; X86-NEXT: xorl %esi, %edx +; X86-NEXT: xorl %esi, %edi +; X86-NEXT: movl %esi, %ebx +; X86-NEXT: subl %edi, %ebx +; X86-NEXT: movl %esi, %edi +; X86-NEXT: sbbl %edx, %edi +; X86-NEXT: movl %esi, %edx +; X86-NEXT: sbbl %ecx, %edx +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, (%eax) ; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: movl %esi, 8(%eax) -; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %esi, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -1175,35 +1197,39 @@ define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_subnsw_i128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: movl %ebx, %ebp -; X86-NEXT: subl %edi, %ebp -; X86-NEXT: movl %ebx, %edi -; X86-NEXT: sbbl %esi, %edi -; X86-NEXT: movl %ebx, %esi -; X86-NEXT: sbbl %edx, %esi -; X86-NEXT: sbbl %ecx, %ebx -; X86-NEXT: movl %ebp, (%eax) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %edx +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %edx +; X86-NEXT: sbbl 48(%ebp), %ecx +; X86-NEXT: sbbl 52(%ebp), %eax +; X86-NEXT: movl %eax, %esi +; X86-NEXT: sarl $31, %esi +; X86-NEXT: xorl %esi, %eax +; X86-NEXT: xorl %esi, %ecx +; X86-NEXT: xorl %esi, %edx +; X86-NEXT: xorl %esi, %edi +; X86-NEXT: movl %esi, %ebx +; X86-NEXT: subl %edi, %ebx +; X86-NEXT: movl %esi, %edi +; X86-NEXT: sbbl %edx, %edi +; X86-NEXT: movl %esi, %edx +; X86-NEXT: sbbl %ecx, %edx +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, (%eax) ; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: movl %esi, 8(%eax) -; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %esi, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/abds.ll b/llvm/test/CodeGen/X86/abds.ll index 0356c2702a419..a1a4ba81ae493 100644 --- a/llvm/test/CodeGen/X86/abds.ll +++ b/llvm/test/CodeGen/X86/abds.ll @@ -343,37 +343,41 @@ define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovll %ebx, %esi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: cmovll %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: sbbl 36(%ebp), %ebx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -404,37 +408,41 @@ define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovll %ebx, %esi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: cmovll %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: sbbl 36(%ebp), %ebx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -585,37 +593,41 @@ define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_minmax_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovll %ebx, %esi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: cmovll %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: sbbl 36(%ebp), %ebx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -768,37 +780,41 @@ define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_cmp_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovll %ebx, %esi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: cmovll %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: sbbl 36(%ebp), %ebx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -1027,35 +1043,38 @@ define i64 @abd_subnsw_i64_undef(i64 %a, i64 %b) nounwind { define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_subnsw_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_subnsw_i128: @@ -1079,35 +1098,38 @@ define i128 @abd_subnsw_i128(i128 %a, i128 %b) nounwind { define i128 @abd_subnsw_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_subnsw_i128_undef: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_subnsw_i128_undef: @@ -1282,37 +1304,41 @@ define i128 @abd_select_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_select_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: subl %edx, %eax -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %edi, %eax -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll (%esp), %edx # 4-byte Folded Reload -; X86-NEXT: cmovll %ebx, %esi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: cmovll %eax, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: subl 24(%ebp), %ecx +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: sbbl 36(%ebp), %ebx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovll %edi, %esi +; X86-NEXT: cmovll %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/abdu-neg.ll b/llvm/test/CodeGen/X86/abdu-neg.ll index 6bda99c89a37e..b7c34070f1af6 100644 --- a/llvm/test/CodeGen/X86/abdu-neg.ll +++ b/llvm/test/CodeGen/X86/abdu-neg.ll @@ -355,39 +355,43 @@ define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %edi, %edi -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebp, %ebp -; X86-NEXT: xorl %ebp, %ecx -; X86-NEXT: xorl %ebp, %esi -; X86-NEXT: xorl %ebp, %ebx -; X86-NEXT: xorl %ebp, %edx -; X86-NEXT: subl %ebp, %edx -; X86-NEXT: sbbl %ebp, %ebx -; X86-NEXT: sbbl %ebp, %esi -; X86-NEXT: sbbl %ebp, %ecx -; X86-NEXT: negl %edx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebx, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: subl 40(%ebp), %ecx +; X86-NEXT: sbbl 44(%ebp), %edi +; X86-NEXT: sbbl 48(%ebp), %esi +; X86-NEXT: sbbl 52(%ebp), %eax ; X86-NEXT: movl $0, %ebx -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: sbbl %ecx, %edi -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: sbbl %ebx, %ebx +; X86-NEXT: xorl %ebx, %eax +; X86-NEXT: xorl %ebx, %esi +; X86-NEXT: xorl %ebx, %edi +; X86-NEXT: xorl %ebx, %ecx +; X86-NEXT: subl %ebx, %ecx +; X86-NEXT: sbbl %ebx, %edi +; X86-NEXT: sbbl %ebx, %esi +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: negl %ecx +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl $0, %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: movl %ebx, 4(%eax) +; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -423,39 +427,43 @@ define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %edi, %edi -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebp, %ebp -; X86-NEXT: xorl %ebp, %ecx -; X86-NEXT: xorl %ebp, %esi -; X86-NEXT: xorl %ebp, %ebx -; X86-NEXT: xorl %ebp, %edx -; X86-NEXT: subl %ebp, %edx -; X86-NEXT: sbbl %ebp, %ebx -; X86-NEXT: sbbl %ebp, %esi -; X86-NEXT: sbbl %ebp, %ecx -; X86-NEXT: negl %edx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebx, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: subl 40(%ebp), %ecx +; X86-NEXT: sbbl 44(%ebp), %edi +; X86-NEXT: sbbl 48(%ebp), %esi +; X86-NEXT: sbbl 52(%ebp), %eax +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %ebx, %ebx +; X86-NEXT: xorl %ebx, %eax +; X86-NEXT: xorl %ebx, %esi +; X86-NEXT: xorl %ebx, %edi +; X86-NEXT: xorl %ebx, %ecx +; X86-NEXT: subl %ebx, %ecx +; X86-NEXT: sbbl %ebx, %edi +; X86-NEXT: sbbl %ebx, %esi +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: negl %ecx ; X86-NEXT: movl $0, %ebx -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: sbbl %ecx, %edi -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl $0, %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: movl %ebx, 4(%eax) +; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -621,55 +629,59 @@ define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_minmax_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: cmpl %eax, %esi -; X86-NEXT: sbbl %ebx, %ecx -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: sbbl %ebp, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: sbbl %edi, %ecx -; X86-NEXT: movl %edi, %ecx -; X86-NEXT: cmovbl %edx, %ecx -; X86-NEXT: movl %ecx, (%esp) # 4-byte Spill -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl %ebx, %ecx -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %eax, %edx -; X86-NEXT: cmovbl %esi, %edx -; X86-NEXT: cmpl %esi, %eax -; X86-NEXT: movl %ebx, %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl %edi, %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: subl %eax, %edx -; X86-NEXT: sbbl %ebx, %ecx -; X86-NEXT: sbbl %esi, %ebp -; X86-NEXT: movl (%esp), %esi # 4-byte Reload -; X86-NEXT: sbbl %edi, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: movl %ecx, 4(%eax) -; X86-NEXT: movl %ebp, 8(%eax) -; X86-NEXT: movl %esi, 12(%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %esi +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: cmpl %esi, %edi +; X86-NEXT: sbbl 44(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %eax +; X86-NEXT: sbbl %edx, %eax +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: movl %ebx, %eax +; X86-NEXT: cmovbl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %edx, %eax +; X86-NEXT: cmovbl 32(%ebp), %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: cmovbl 28(%ebp), %eax +; X86-NEXT: movl %esi, %ecx +; X86-NEXT: cmovbl %edi, %ecx +; X86-NEXT: cmpl %edi, %esi +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: sbbl 28(%ebp), %edi +; X86-NEXT: movl %edx, %edi +; X86-NEXT: sbbl 32(%ebp), %edi +; X86-NEXT: movl %ebx, %edi +; X86-NEXT: sbbl 36(%ebp), %edi +; X86-NEXT: cmovbl 36(%ebp), %ebx +; X86-NEXT: cmovbl 32(%ebp), %edx +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: cmovbl 28(%ebp), %edi +; X86-NEXT: cmovbl 24(%ebp), %esi +; X86-NEXT: subl %esi, %ecx +; X86-NEXT: sbbl %edi, %eax +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload +; X86-NEXT: sbbl %edx, %edi +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload +; X86-NEXT: sbbl %ebx, %esi +; X86-NEXT: movl 8(%ebp), %edx +; X86-NEXT: movl %ecx, (%edx) +; X86-NEXT: movl %eax, 4(%edx) +; X86-NEXT: movl %edi, 8(%edx) +; X86-NEXT: movl %esi, 12(%edx) +; X86-NEXT: movl %edx, %eax +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -827,39 +839,43 @@ define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_cmp_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %edi, %edi -; X86-NEXT: subl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebp, %ebp -; X86-NEXT: xorl %ebp, %ecx -; X86-NEXT: xorl %ebp, %esi -; X86-NEXT: xorl %ebp, %ebx -; X86-NEXT: xorl %ebp, %edx -; X86-NEXT: subl %ebp, %edx -; X86-NEXT: sbbl %ebp, %ebx -; X86-NEXT: sbbl %ebp, %esi -; X86-NEXT: sbbl %ebp, %ecx -; X86-NEXT: negl %edx -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %ebx, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: subl 40(%ebp), %ecx +; X86-NEXT: sbbl 44(%ebp), %edi +; X86-NEXT: sbbl 48(%ebp), %esi +; X86-NEXT: sbbl 52(%ebp), %eax +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %ebx, %ebx +; X86-NEXT: xorl %ebx, %eax +; X86-NEXT: xorl %ebx, %esi +; X86-NEXT: xorl %ebx, %edi +; X86-NEXT: xorl %ebx, %ecx +; X86-NEXT: subl %ebx, %ecx +; X86-NEXT: sbbl %ebx, %edi +; X86-NEXT: sbbl %ebx, %esi +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: negl %ecx ; X86-NEXT: movl $0, %ebx -; X86-NEXT: sbbl %esi, %ebx -; X86-NEXT: sbbl %ecx, %edi -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl $0, %edi +; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: movl %ebx, 4(%eax) +; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/abdu.ll b/llvm/test/CodeGen/X86/abdu.ll index 27acec32fd348..043c9155f52f9 100644 --- a/llvm/test/CodeGen/X86/abdu.ll +++ b/llvm/test/CodeGen/X86/abdu.ll @@ -326,35 +326,38 @@ define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind { define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl %ebx, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: sbbl %eax, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_ext_i128: @@ -381,35 +384,38 @@ define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_ext_i128_undef: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl %ebx, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: sbbl %eax, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_ext_i128_undef: @@ -548,35 +554,38 @@ define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind { define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_minmax_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl %ebx, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: sbbl %eax, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_minmax_i128: @@ -717,35 +726,38 @@ define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind { define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_cmp_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl %ebx, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: sbbl %eax, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_cmp_i128: @@ -887,35 +899,38 @@ define i64 @abd_select_i64(i64 %a, i64 %b) nounwind { define i128 @abd_select_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: abd_select_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: subl {{[0-9]+}}(%esp), %edi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: sbbl %ebx, %ebx -; X86-NEXT: xorl %ebx, %ecx -; X86-NEXT: xorl %ebx, %edx -; X86-NEXT: xorl %ebx, %esi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: subl %ebx, %edi -; X86-NEXT: sbbl %ebx, %esi -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl %ebx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: subl 40(%ebp), %edi +; X86-NEXT: sbbl 44(%ebp), %esi +; X86-NEXT: sbbl 48(%ebp), %edx +; X86-NEXT: sbbl 52(%ebp), %ecx +; X86-NEXT: sbbl %eax, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: abd_select_i128: diff --git a/llvm/test/CodeGen/X86/abs.ll b/llvm/test/CodeGen/X86/abs.ll index bae140abdf6b1..e252d5953e60e 100644 --- a/llvm/test/CodeGen/X86/abs.ll +++ b/llvm/test/CodeGen/X86/abs.ll @@ -144,31 +144,34 @@ define i128 @test_i128(i128 %a) nounwind { ; ; X86-LABEL: test_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %edx -; X86-NEXT: sarl $31, %edx -; X86-NEXT: xorl %edx, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: xorl %edx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: xorl %edx, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: xorl %edx, %ebx -; X86-NEXT: subl %edx, %ebx -; X86-NEXT: sbbl %edx, %edi -; X86-NEXT: sbbl %edx, %esi -; X86-NEXT: sbbl %edx, %ecx -; X86-NEXT: movl %ebx, (%eax) -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edi, (%eax) +; X86-NEXT: movl %esi, 4(%eax) +; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %r = call i128 @llvm.abs.i128(i128 %a, i1 false) ret i128 %r @@ -688,13 +691,17 @@ define i128 @test_sextinreg_i128(i128 %a) nounwind { ; ; X86-LABEL: test_sextinreg_i128: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %ecx ; X86-NEXT: movl %ecx, %edx ; X86-NEXT: sarl $31, %edx ; X86-NEXT: xorl %edx, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl 24(%ebp), %esi ; X86-NEXT: xorl %edx, %esi ; X86-NEXT: subl %edx, %esi ; X86-NEXT: sbbl %edx, %ecx @@ -702,7 +709,9 @@ define i128 @test_sextinreg_i128(i128 %a) nounwind { ; X86-NEXT: movl %ecx, 4(%eax) ; X86-NEXT: movl $0, 12(%eax) ; X86-NEXT: movl $0, 8(%eax) +; X86-NEXT: leal -4(%ebp), %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %shl = shl i128 %a, 64 %ashr = ashr exact i128 %shl, 64 diff --git a/llvm/test/CodeGen/X86/add-sub-bool.ll b/llvm/test/CodeGen/X86/add-sub-bool.ll index c2bfcf57185e3..1df284fb9fe2c 100644 --- a/llvm/test/CodeGen/X86/add-sub-bool.ll +++ b/llvm/test/CodeGen/X86/add-sub-bool.ll @@ -104,18 +104,21 @@ define i24 @test_i24_add_add_idx(i24 %x, i24 %y, i24 %z) nounwind { define i128 @test_i128_add_add_idx(i128 %x, i128 %y, i128 %z) nounwind { ; X86-LABEL: test_i128_add_add_idx: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: addl {{[0-9]+}}(%esp), %esi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %edi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: adcl {{[0-9]+}}(%esp), %edx -; X86-NEXT: btl $5, {{[0-9]+}}(%esp) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %ecx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: movl 40(%ebp), %esi +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: addl 24(%ebp), %esi +; X86-NEXT: adcl 28(%ebp), %edi +; X86-NEXT: adcl 32(%ebp), %ecx +; X86-NEXT: adcl 36(%ebp), %edx +; X86-NEXT: btl $5, 64(%ebp) ; X86-NEXT: adcl $0, %esi ; X86-NEXT: adcl $0, %edi ; X86-NEXT: adcl $0, %ecx @@ -124,8 +127,10 @@ define i128 @test_i128_add_add_idx(i128 %x, i128 %y, i128 %z) nounwind { ; X86-NEXT: movl %esi, (%eax) ; X86-NEXT: movl %ecx, 8(%eax) ; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: test_i128_add_add_idx: diff --git a/llvm/test/CodeGen/X86/arg-copy-elide.ll b/llvm/test/CodeGen/X86/arg-copy-elide.ll index 0eb2c630e6818..f13627b55856f 100644 --- a/llvm/test/CodeGen/X86/arg-copy-elide.ll +++ b/llvm/test/CodeGen/X86/arg-copy-elide.ll @@ -188,11 +188,11 @@ define void @split_i128(ptr %sret, i128 %x) { ; CHECK-NEXT: pushl %esi ; CHECK-NEXT: andl $-16, %esp ; CHECK-NEXT: subl $48, %esp -; CHECK-NEXT: movl 12(%ebp), %eax +; CHECK-NEXT: movl 24(%ebp), %eax ; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; CHECK-NEXT: movl 16(%ebp), %ebx -; CHECK-NEXT: movl 20(%ebp), %esi -; CHECK-NEXT: movl 24(%ebp), %edi +; CHECK-NEXT: movl 28(%ebp), %ebx +; CHECK-NEXT: movl 32(%ebp), %esi +; CHECK-NEXT: movl 36(%ebp), %edi ; CHECK-NEXT: movl %edi, {{[0-9]+}}(%esp) ; CHECK-NEXT: movl %esi, {{[0-9]+}}(%esp) ; CHECK-NEXT: movl %ebx, {{[0-9]+}}(%esp) diff --git a/llvm/test/CodeGen/X86/avg.ll b/llvm/test/CodeGen/X86/avg.ll index 217ccebdfb77f..0de308a9e0738 100644 --- a/llvm/test/CodeGen/X86/avg.ll +++ b/llvm/test/CodeGen/X86/avg.ll @@ -1734,20 +1734,20 @@ define void @not_avg_v16i8_wide_constants(ptr %a, ptr %b) nounwind { ; SSE2-LABEL: not_avg_v16i8_wide_constants: ; SSE2: # %bb.0: ; SSE2-NEXT: movaps (%rdi), %xmm1 -; SSE2-NEXT: movdqa (%rsi), %xmm2 +; SSE2-NEXT: movdqa (%rsi), %xmm0 ; SSE2-NEXT: movaps %xmm1, -{{[0-9]+}}(%rsp) ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax -; SSE2-NEXT: movd %eax, %xmm0 +; SSE2-NEXT: movd %eax, %xmm2 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax ; SSE2-NEXT: movd %eax, %xmm1 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax -; SSE2-NEXT: movd %eax, %xmm4 +; SSE2-NEXT: movd %eax, %xmm3 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax -; SSE2-NEXT: movd %eax, %xmm3 +; SSE2-NEXT: movd %eax, %xmm4 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax ; SSE2-NEXT: movd %eax, %xmm5 @@ -1762,6 +1762,9 @@ define void @not_avg_v16i8_wide_constants(ptr %a, ptr %b) nounwind { ; SSE2-NEXT: movd %eax, %xmm8 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax +; SSE2-NEXT: movd %eax, %xmm10 +; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SSE2-NEXT: decl %eax ; SSE2-NEXT: movd %eax, %xmm9 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax @@ -1771,9 +1774,6 @@ define void @not_avg_v16i8_wide_constants(ptr %a, ptr %b) nounwind { ; SSE2-NEXT: movd %eax, %xmm12 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax -; SSE2-NEXT: movd %eax, %xmm10 -; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax -; SSE2-NEXT: decl %eax ; SSE2-NEXT: movd %eax, %xmm13 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax @@ -1783,43 +1783,45 @@ define void @not_avg_v16i8_wide_constants(ptr %a, ptr %b) nounwind { ; SSE2-NEXT: movd %eax, %xmm15 ; SSE2-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax ; SSE2-NEXT: decl %eax -; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3] -; SSE2-NEXT: movd %eax, %xmm0 -; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3] -; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3] +; SSE2-NEXT: movd %eax, %xmm2 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3] +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm4[0,0,0,0] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] ; SSE2-NEXT: punpcklwd {{.*#+}} xmm6 = xmm6[0],xmm5[0],xmm6[1],xmm5[1],xmm6[2],xmm5[2],xmm6[3],xmm5[3] -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm6[0,0,0,0] +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm6[0,0,0,0] ; SSE2-NEXT: punpcklwd {{.*#+}} xmm8 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3] ; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm8[0,0,0,0] -; SSE2-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm1[2],xmm4[3],xmm1[3] -; SSE2-NEXT: movsd {{.*#+}} xmm4 = xmm3[0],xmm4[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm3[2],xmm4[3],xmm3[3] +; SSE2-NEXT: movsd {{.*#+}} xmm4 = xmm1[0],xmm4[1] ; SSE2-NEXT: pxor %xmm3, %xmm3 -; SSE2-NEXT: movdqa %xmm2, %xmm1 +; SSE2-NEXT: movdqa %xmm0, %xmm1 ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] ; SSE2-NEXT: movapd %xmm4, %xmm5 ; SSE2-NEXT: andpd %xmm1, %xmm5 ; SSE2-NEXT: xorpd %xmm4, %xmm1 ; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: paddw %xmm5, %xmm1 -; SSE2-NEXT: punpcklwd {{.*#+}} xmm11 = xmm11[0],xmm9[0],xmm11[1],xmm9[1],xmm11[2],xmm9[2],xmm11[3],xmm9[3] -; SSE2-NEXT: punpcklwd {{.*#+}} xmm10 = xmm10[0],xmm12[0],xmm10[1],xmm12[1],xmm10[2],xmm12[2],xmm10[3],xmm12[3] -; SSE2-NEXT: punpckldq {{.*#+}} xmm10 = xmm10[0],xmm11[0],xmm10[1],xmm11[1] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm9 = xmm9[0],xmm10[0],xmm9[1],xmm10[1],xmm9[2],xmm10[2],xmm9[3],xmm10[3] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm12 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3] +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm12[0,0,0,0] +; SSE2-NEXT: punpckldq {{.*#+}} xmm9 = xmm9[0],xmm4[0],xmm9[1],xmm4[1] ; SSE2-NEXT: punpcklwd {{.*#+}} xmm14 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3] ; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm14[0,0,0,0] -; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm15[0],xmm0[1],xmm15[1],xmm0[2],xmm15[2],xmm0[3],xmm15[3] -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,0,0] -; SSE2-NEXT: punpckhdq {{.*#+}} xmm0 = xmm0[2],xmm4[2],xmm0[3],xmm4[3] -; SSE2-NEXT: movsd {{.*#+}} xmm0 = xmm10[0],xmm0[1] -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] -; SSE2-NEXT: movapd %xmm0, %xmm3 -; SSE2-NEXT: andpd %xmm2, %xmm3 -; SSE2-NEXT: xorpd %xmm0, %xmm2 -; SSE2-NEXT: psrlw $1, %xmm2 -; SSE2-NEXT: paddw %xmm3, %xmm2 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: packuswb %xmm2, %xmm1 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm15[0],xmm2[1],xmm15[1],xmm2[2],xmm15[2],xmm2[3],xmm15[3] +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,0,0,0] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm4[2],xmm2[3],xmm4[3] +; SSE2-NEXT: movsd {{.*#+}} xmm2 = xmm9[0],xmm2[1] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; SSE2-NEXT: movapd %xmm2, %xmm3 +; SSE2-NEXT: andpd %xmm0, %xmm3 +; SSE2-NEXT: xorpd %xmm2, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: paddw %xmm3, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm2, %xmm1 +; SSE2-NEXT: packuswb %xmm0, %xmm1 ; SSE2-NEXT: movdqu %xmm1, (%rax) ; SSE2-NEXT: retq ; @@ -1829,74 +1831,75 @@ define void @not_avg_v16i8_wide_constants(ptr %a, ptr %b) nounwind { ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = mem[0],zero,mem[1],zero,mem[2],zero,mem[3],zero,mem[4],zero,mem[5],zero,mem[6],zero,mem[7],zero -; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 -; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm5 = xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7] -; AVX1-NEXT: vpextrd $2, %xmm5, %ecx -; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm4 = xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] -; AVX1-NEXT: vpextrd $2, %xmm4, %eax -; AVX1-NEXT: vpextrw $3, %xmm3, %edx +; AVX1-NEXT: vpextrw $7, %xmm3, %edx +; AVX1-NEXT: vpextrw $6, %xmm3, %ecx +; AVX1-NEXT: vpextrw $5, %xmm3, %eax ; AVX1-NEXT: decl %edx ; AVX1-NEXT: vmovd %edx, %xmm4 -; AVX1-NEXT: vpextrw $2, %xmm3, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm5 -; AVX1-NEXT: vpextrw $1, %xmm3, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm6 -; AVX1-NEXT: vpextrw $0, %xmm3, %edx +; AVX1-NEXT: vpextrw $4, %xmm3, %edx +; AVX1-NEXT: decl %ecx +; AVX1-NEXT: vmovd %ecx, %xmm5 +; AVX1-NEXT: vpextrw $1, %xmm3, %ecx +; AVX1-NEXT: decl %eax +; AVX1-NEXT: vmovd %eax, %xmm6 +; AVX1-NEXT: vpextrw $0, %xmm3, %eax ; AVX1-NEXT: decl %edx ; AVX1-NEXT: vmovd %edx, %xmm7 -; AVX1-NEXT: vpextrw $3, %xmm2, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm8 -; AVX1-NEXT: vpextrw $2, %xmm2, %edx +; AVX1-NEXT: vpextrw $3, %xmm3, %edx +; AVX1-NEXT: decq %rcx +; AVX1-NEXT: vmovq %rcx, %xmm8 +; AVX1-NEXT: vpextrw $2, %xmm3, %ecx +; AVX1-NEXT: decq %rax +; AVX1-NEXT: vmovq %rax, %xmm3 +; AVX1-NEXT: vpextrw $7, %xmm2, %eax ; AVX1-NEXT: decl %edx ; AVX1-NEXT: vmovd %edx, %xmm9 -; AVX1-NEXT: vpextrw $1, %xmm2, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm10 -; AVX1-NEXT: vpextrw $0, %xmm2, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm11 -; AVX1-NEXT: vpextrw $5, %xmm3, %edx +; AVX1-NEXT: vpextrw $6, %xmm2, %edx +; AVX1-NEXT: decl %ecx +; AVX1-NEXT: vmovd %ecx, %xmm10 +; AVX1-NEXT: vpextrw $5, %xmm2, %ecx +; AVX1-NEXT: decl %eax +; AVX1-NEXT: vmovd %eax, %xmm11 +; AVX1-NEXT: vpextrw $4, %xmm2, %eax ; AVX1-NEXT: decl %edx ; AVX1-NEXT: vmovd %edx, %xmm12 -; AVX1-NEXT: vpextrw $4, %xmm3, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm13 -; AVX1-NEXT: vpextrw $5, %xmm2, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm14 -; AVX1-NEXT: vpextrw $4, %xmm2, %edx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm15 -; AVX1-NEXT: vpextrw $7, %xmm3, %edx +; AVX1-NEXT: vpextrw $1, %xmm2, %edx ; AVX1-NEXT: decl %ecx -; AVX1-NEXT: vmovd %ecx, %xmm3 -; AVX1-NEXT: vpextrw $7, %xmm2, %ecx -; AVX1-NEXT: decl %edx -; AVX1-NEXT: vmovd %edx, %xmm2 +; AVX1-NEXT: vmovd %ecx, %xmm13 +; AVX1-NEXT: vpextrw $0, %xmm2, %ecx +; AVX1-NEXT: decl %eax +; AVX1-NEXT: vmovd %eax, %xmm14 +; AVX1-NEXT: vpextrw $3, %xmm2, %eax +; AVX1-NEXT: decq %rdx +; AVX1-NEXT: vmovq %rdx, %xmm15 +; AVX1-NEXT: vpextrw $2, %xmm2, %edx +; AVX1-NEXT: decq %rcx +; AVX1-NEXT: vmovq %rcx, %xmm2 ; AVX1-NEXT: decl %eax ; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm4 = xmm5[0],xmm4[0],xmm5[1],xmm4[1],xmm5[2],xmm4[2],xmm5[3],xmm4[3] ; AVX1-NEXT: vmovd %eax, %xmm5 -; AVX1-NEXT: decl %ecx +; AVX1-NEXT: decl %edx ; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm6 = xmm7[0],xmm6[0],xmm7[1],xmm6[1],xmm7[2],xmm6[2],xmm7[3],xmm6[3] -; AVX1-NEXT: vmovd %ecx, %xmm7 -; AVX1-NEXT: vpunpckldq {{.*#+}} xmm4 = xmm6[0],xmm4[0],xmm6[1],xmm4[1] -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm6 = xmm9[0],xmm8[0],xmm9[1],xmm8[1],xmm9[2],xmm8[2],xmm9[3],xmm8[3] -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm8 = xmm11[0],xmm10[0],xmm11[1],xmm10[1],xmm11[2],xmm10[2],xmm11[3],xmm10[3] -; AVX1-NEXT: vpunpckldq {{.*#+}} xmm6 = xmm8[0],xmm6[0],xmm8[1],xmm6[1] -; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm6, %ymm4 -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm6 = xmm13[0],xmm12[0],xmm13[1],xmm12[1],xmm13[2],xmm12[2],xmm13[3],xmm12[3] -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm8 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3] -; AVX1-NEXT: vinsertf128 $1, %xmm6, %ymm8, %ymm6 -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[1],xmm2[1],xmm3[2],xmm2[2],xmm3[3],xmm2[3] -; AVX1-NEXT: vmovddup {{.*#+}} ymm3 = ymm6[0,0,2,2] -; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm5 = xmm5[0],xmm7[0],xmm5[1],xmm7[1],xmm5[2],xmm7[2],xmm5[3],xmm7[3] -; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm5, %ymm2 -; AVX1-NEXT: vshufps {{.*#+}} ymm2 = ymm2[0,0,0,0,4,4,4,4] -; AVX1-NEXT: vblendps {{.*#+}} ymm2 = ymm3[0,1,2],ymm2[3],ymm3[4,5,6],ymm2[7] -; AVX1-NEXT: vblendps {{.*#+}} ymm2 = ymm4[0,1],ymm2[2,3],ymm4[4,5],ymm2[6,7] +; AVX1-NEXT: vmovd %edx, %xmm7 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm4[0,0,0,0] +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm6[0,1,0,1] +; AVX1-NEXT: vpblendw {{.*#+}} xmm4 = xmm6[0,1,2,3,4,5],xmm4[6,7] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm3 = xmm3[0],xmm8[0],xmm3[1],xmm8[1],xmm3[2],xmm8[2],xmm3[3],xmm8[3] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm6 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3] +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm6[0,0,1,1] +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1],xmm6[2,3],xmm3[4,5,6,7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0,1,2,3],xmm4[4,5,6,7] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm4 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm6 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3] +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm4[0,0,0,0] +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm6[0,1,0,1] +; AVX1-NEXT: vpblendw {{.*#+}} xmm4 = xmm6[0,1,2,3,4,5],xmm4[6,7] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm2 = xmm2[0],xmm15[0],xmm2[1],xmm15[1],xmm2[2],xmm15[2],xmm2[3],xmm15[3] +; AVX1-NEXT: vpunpcklwd {{.*#+}} xmm5 = xmm7[0],xmm5[0],xmm7[1],xmm5[1],xmm7[2],xmm5[2],xmm7[3],xmm5[3] +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[0,0,1,1] +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0,1],xmm5[2,3],xmm2[4,5,6,7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm4[4,5,6,7] +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 ; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 ; AVX1-NEXT: vandps %ymm0, %ymm2, %ymm1 ; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 diff --git a/llvm/test/CodeGen/X86/avx512cfmulsh-instrinsics.ll b/llvm/test/CodeGen/X86/avx512cfmulsh-instrinsics.ll index e449c7192e4bf..b60d7a5463d6b 100644 --- a/llvm/test/CodeGen/X86/avx512cfmulsh-instrinsics.ll +++ b/llvm/test/CodeGen/X86/avx512cfmulsh-instrinsics.ll @@ -278,14 +278,14 @@ define <4 x float> @test_int_x86_avx512fp16_maskz_cfcmadd_sh(<4 x float> %x0, <4 ret <4 x float> %res } -define <4 x float> @PR98306() { +define <4 x float> @PR98306(i8 %m) { ; CHECK-LABEL: PR98306: ; CHECK: ## %bb.0: -; CHECK-NEXT: kxorw %k0, %k0, %k1 +; CHECK-NEXT: kmovd %edi, %k1 ; CHECK-NEXT: vmovaps {{.*#+}} xmm1 = [7.8125E-3,1.050912E+6,4.203776E+6,1.6815616E+7] ; CHECK-NEXT: vmovaps {{.*#+}} xmm0 = [3.2E+1,4.03288064E+8,8.0658432E+8,1.61318502E+9] ; CHECK-NEXT: vfmaddcsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0 {%k1} {z} ; CHECK-NEXT: retq - %res = call <4 x float> @llvm.x86.avx512fp16.maskz.vfmadd.csh(<4 x float> , <4 x float> , <4 x float> , i8 0, i32 4) + %res = call <4 x float> @llvm.x86.avx512fp16.maskz.vfmadd.csh(<4 x float> , <4 x float> , <4 x float> , i8 %m, i32 4) ret <4 x float> %res } diff --git a/llvm/test/CodeGen/X86/avx512fp16-cvt.ll b/llvm/test/CodeGen/X86/avx512fp16-cvt.ll index f66f0c0ceabc4..cc58bc1e44f37 100644 --- a/llvm/test/CodeGen/X86/avx512fp16-cvt.ll +++ b/llvm/test/CodeGen/X86/avx512fp16-cvt.ll @@ -628,13 +628,19 @@ define half @s128_to_half(i128 %x) { ; ; X86-LABEL: s128_to_half: ; X86: # %bb.0: -; X86-NEXT: subl $16, %esp -; X86-NEXT: .cfi_def_cfa_offset 20 -; X86-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $32, %esp +; X86-NEXT: vmovups 8(%ebp), %xmm0 ; X86-NEXT: vmovups %xmm0, (%esp) ; X86-NEXT: calll __floattihf -; X86-NEXT: addl $16, %esp -; X86-NEXT: .cfi_def_cfa_offset 4 +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl %a = sitofp i128 %x to half ret half %a @@ -713,13 +719,19 @@ define half @u128_to_half(i128 %x) { ; ; X86-LABEL: u128_to_half: ; X86: # %bb.0: -; X86-NEXT: subl $16, %esp -; X86-NEXT: .cfi_def_cfa_offset 20 -; X86-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $32, %esp +; X86-NEXT: vmovups 8(%ebp), %xmm0 ; X86-NEXT: vmovups %xmm0, (%esp) ; X86-NEXT: calll __floatuntihf -; X86-NEXT: addl $16, %esp -; X86-NEXT: .cfi_def_cfa_offset 4 +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl %a = uitofp i128 %x to half ret half %a @@ -1020,11 +1032,15 @@ define half @f128_to_half(fp128 %x) nounwind { ; ; X86-LABEL: f128_to_half: ; X86: # %bb.0: -; X86-NEXT: subl $16, %esp -; X86-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $32, %esp +; X86-NEXT: vmovups 8(%ebp), %xmm0 ; X86-NEXT: vmovups %xmm0, (%esp) ; X86-NEXT: calll __trunctfhf2 -; X86-NEXT: addl $16, %esp +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl %a = fptrunc fp128 %x to half ret half %a diff --git a/llvm/test/CodeGen/X86/avx512fp16-intrinsics.ll b/llvm/test/CodeGen/X86/avx512fp16-intrinsics.ll index 627a94799424c..b1bacd92f073b 100644 --- a/llvm/test/CodeGen/X86/avx512fp16-intrinsics.ll +++ b/llvm/test/CodeGen/X86/avx512fp16-intrinsics.ll @@ -1361,3 +1361,19 @@ define <32 x half> @test_mm512_castph256_ph512_freeze(<16 x half> %a0) nounwind %res = shufflevector <16 x half> %a0, <16 x half> %a1, <32 x i32> ret <32 x half> %res } + +define <8 x half> @PR153570(ptr %p) { +; CHECK-LABEL: PR153570: +; CHECK: # %bb.0: +; CHECK-NEXT: vpbroadcastw {{.*#+}} xmm0 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; CHECK-NEXT: vpbroadcastw {{.*#+}} xmm1 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0,1.0E+0,1.0E+0,1.0E+0,1.0E+0] +; CHECK-NEXT: vmulsh {rn-sae}, %xmm0, %xmm1, %xmm0 +; CHECK-NEXT: vpbroadcastw {{.*#+}} xmm2 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0] +; CHECK-NEXT: vmovsh %xmm2, %xmm1, %xmm1 +; CHECK-NEXT: vmovaps %xmm1, (%rdi) +; CHECK-NEXT: retq + %r = tail call <8 x half> @llvm.x86.avx512fp16.mask.mul.sh.round(<8 x half> , <8 x half> , <8 x half> , i8 0, i32 8) + store <8 x half> %r, ptr %p, align 16 + %r1 = tail call <8 x half> @llvm.x86.avx512fp16.mask.mul.sh.round(<8 x half> , <8 x half> , <8 x half> , i8 1, i32 8) + ret <8 x half> %r1 +} diff --git a/llvm/test/CodeGen/X86/bitselect.ll b/llvm/test/CodeGen/X86/bitselect.ll index 4fc0827ac4dd6..33381313d3c19 100644 --- a/llvm/test/CodeGen/X86/bitselect.ll +++ b/llvm/test/CodeGen/X86/bitselect.ll @@ -146,37 +146,40 @@ define i64 @bitselect_i64(i64 %a, i64 %b, i64 %m) nounwind { define i128 @bitselect_i128(i128 %a, i128 %b, i128 %m) nounwind { ; X86-LABEL: bitselect_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: xorl %edi, %ecx -; X86-NEXT: andl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: xorl %edi, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: andl {{[0-9]+}}(%esp), %edi -; X86-NEXT: xorl %ebx, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: xorl %esi, %ebx -; X86-NEXT: andl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: xorl %esi, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: xorl %edx, %esi -; X86-NEXT: andl {{[0-9]+}}(%esp), %esi -; X86-NEXT: xorl %edx, %esi -; X86-NEXT: movl %esi, 12(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %esi +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: xorl %esi, %ecx +; X86-NEXT: andl 56(%ebp), %ecx +; X86-NEXT: xorl %esi, %ecx +; X86-NEXT: movl 44(%ebp), %esi +; X86-NEXT: xorl %edi, %esi +; X86-NEXT: andl 60(%ebp), %esi +; X86-NEXT: xorl %edi, %esi +; X86-NEXT: movl 48(%ebp), %edi +; X86-NEXT: xorl %edx, %edi +; X86-NEXT: andl 64(%ebp), %edi +; X86-NEXT: xorl %edx, %edi +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: andl 68(%ebp), %edx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-NOBMI-LABEL: bitselect_i128: diff --git a/llvm/test/CodeGen/X86/bsf.ll b/llvm/test/CodeGen/X86/bsf.ll index 312f94c041235..143e10e6909e4 100644 --- a/llvm/test/CodeGen/X86/bsf.ll +++ b/llvm/test/CodeGen/X86/bsf.ll @@ -263,70 +263,78 @@ define i128 @cmov_bsf128(i128 %x, i128 %y) nounwind { ; X86-LABEL: cmov_bsf128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %edi, %edx -; X86-NEXT: orl %ebp, %edx -; X86-NEXT: movl %ecx, %esi -; X86-NEXT: orl %eax, %esi -; X86-NEXT: orl %edx, %esi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %ebx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: movl %esi, %eax +; X86-NEXT: orl %ebx, %eax +; X86-NEXT: movl %ecx, %edx +; X86-NEXT: orl %edi, %edx +; X86-NEXT: orl %eax, %edx ; X86-NEXT: je .LBB8_1 ; X86-NEXT: # %bb.2: # %cond.false ; X86-NEXT: testl %ecx, %ecx ; X86-NEXT: jne .LBB8_3 ; X86-NEXT: # %bb.4: # %cond.false -; X86-NEXT: rep bsfl %edi, %esi -; X86-NEXT: addl $32, %esi -; X86-NEXT: testl %eax, %eax -; X86-NEXT: je .LBB8_7 -; X86-NEXT: .LBB8_6: -; X86-NEXT: rep bsfl %eax, %edx -; X86-NEXT: jmp .LBB8_8 +; X86-NEXT: rep bsfl %esi, %eax +; X86-NEXT: addl $32, %eax +; X86-NEXT: jmp .LBB8_5 ; X86-NEXT: .LBB8_1: -; X86-NEXT: movl %ebp, %eax -; X86-NEXT: xorl %ebp, %ebp -; X86-NEXT: movl $128, %esi +; X86-NEXT: movl %ebx, %eax +; X86-NEXT: xorl %edi, %edi +; X86-NEXT: movl $128, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill ; X86-NEXT: jmp .LBB8_11 ; X86-NEXT: .LBB8_3: -; X86-NEXT: rep bsfl %ecx, %esi -; X86-NEXT: testl %eax, %eax +; X86-NEXT: rep bsfl %ecx, %eax +; X86-NEXT: .LBB8_5: # %cond.false +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: testl %edi, %edi ; X86-NEXT: jne .LBB8_6 -; X86-NEXT: .LBB8_7: # %cond.false -; X86-NEXT: rep bsfl %ebp, %edx +; X86-NEXT: # %bb.7: # %cond.false +; X86-NEXT: rep bsfl %ebx, %edx ; X86-NEXT: addl $32, %edx +; X86-NEXT: jmp .LBB8_8 +; X86-NEXT: .LBB8_6: +; X86-NEXT: rep bsfl %edi, %edx ; X86-NEXT: .LBB8_8: # %cond.false -; X86-NEXT: movl %ebp, %eax -; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: orl %edi, %ebx +; X86-NEXT: movl %ebx, %eax +; X86-NEXT: movl %ecx, %edi +; X86-NEXT: orl %esi, %edi ; X86-NEXT: jne .LBB8_10 ; X86-NEXT: # %bb.9: # %cond.false ; X86-NEXT: addl $64, %edx -; X86-NEXT: movl %edx, %esi +; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: .LBB8_10: # %cond.false -; X86-NEXT: xorl %ebp, %ebp +; X86-NEXT: xorl %edi, %edi ; X86-NEXT: .LBB8_11: # %cond.end -; X86-NEXT: xorl %ebx, %ebx ; X86-NEXT: xorl %edx, %edx -; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: orl %eax, %edi -; X86-NEXT: orl %ecx, %edi -; X86-NEXT: jne .LBB8_13 -; X86-NEXT: # %bb.12: -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: .LBB8_13: # %cond.end -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edx, 12(%eax) -; X86-NEXT: movl %ebx, 8(%eax) -; X86-NEXT: movl %ebp, 4(%eax) -; X86-NEXT: movl %esi, (%eax) +; X86-NEXT: xorl %ebx, %ebx +; X86-NEXT: orl 32(%ebp), %ecx +; X86-NEXT: orl %eax, %esi +; X86-NEXT: orl %ecx, %esi +; X86-NEXT: je .LBB8_12 +; X86-NEXT: # %bb.13: # %cond.end +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: jmp .LBB8_14 +; X86-NEXT: .LBB8_12: +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: .LBB8_14: # %cond.end +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -361,46 +369,49 @@ define i128 @cmov_bsf128_undef(i128 %x, i128 %y) nounwind { ; X86-LABEL: cmov_bsf128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl %ecx, %edi -; X86-NEXT: orl %esi, %edi -; X86-NEXT: movl %edx, %ebp -; X86-NEXT: orl %ebx, %ebp -; X86-NEXT: orl %edi, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: orl %esi, %eax +; X86-NEXT: movl %edx, %ebx +; X86-NEXT: orl %edi, %ebx +; X86-NEXT: orl %eax, %ebx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: je .LBB9_11 ; X86-NEXT: # %bb.1: # %select.true.sink ; X86-NEXT: testl %edx, %edx ; X86-NEXT: jne .LBB9_2 ; X86-NEXT: # %bb.3: # %select.true.sink -; X86-NEXT: rep bsfl %ecx, %edi -; X86-NEXT: addl $32, %edi -; X86-NEXT: testl %ebx, %ebx +; X86-NEXT: rep bsfl %ecx, %ebx +; X86-NEXT: addl $32, %ebx +; X86-NEXT: testl %edi, %edi ; X86-NEXT: je .LBB9_6 ; X86-NEXT: .LBB9_5: -; X86-NEXT: rep bsfl %ebx, %esi +; X86-NEXT: rep bsfl %edi, %esi ; X86-NEXT: orl %ecx, %edx ; X86-NEXT: je .LBB9_8 ; X86-NEXT: jmp .LBB9_9 ; X86-NEXT: .LBB9_11: # %select.end -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl 52(%ebp), %ecx +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 44(%ebp), %esi +; X86-NEXT: movl 40(%ebp), %edi ; X86-NEXT: movl %edi, (%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) ; X86-NEXT: jmp .LBB9_10 ; X86-NEXT: .LBB9_2: -; X86-NEXT: rep bsfl %edx, %edi -; X86-NEXT: testl %ebx, %ebx +; X86-NEXT: rep bsfl %edx, %ebx +; X86-NEXT: testl %edi, %edi ; X86-NEXT: jne .LBB9_5 ; X86-NEXT: .LBB9_6: # %select.true.sink ; X86-NEXT: rep bsfl %esi, %esi @@ -409,13 +420,14 @@ define i128 @cmov_bsf128_undef(i128 %x, i128 %y) nounwind { ; X86-NEXT: jne .LBB9_9 ; X86-NEXT: .LBB9_8: # %select.true.sink ; X86-NEXT: addl $64, %esi -; X86-NEXT: movl %esi, %edi +; X86-NEXT: movl %esi, %ebx ; X86-NEXT: .LBB9_9: # %select.true.sink -; X86-NEXT: movl %edi, (%eax) +; X86-NEXT: movl %ebx, (%eax) ; X86-NEXT: movl $0, 12(%eax) ; X86-NEXT: movl $0, 8(%eax) ; X86-NEXT: movl $0, 4(%eax) ; X86-NEXT: .LBB9_10: # %select.true.sink +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/bsr.ll b/llvm/test/CodeGen/X86/bsr.ll index fbca4af425eac..ab0478a4e944b 100644 --- a/llvm/test/CodeGen/X86/bsr.ll +++ b/llvm/test/CodeGen/X86/bsr.ll @@ -291,79 +291,80 @@ define i128 @cmov_bsr128(i128 %x, i128 %y) nounwind { ; X86-LABEL: cmov_bsr128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %edi, %edx -; X86-NEXT: orl %ebp, %edx -; X86-NEXT: movl %ecx, %esi -; X86-NEXT: orl %ebx, %esi -; X86-NEXT: orl %edx, %esi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: movl %edi, %eax +; X86-NEXT: orl %esi, %eax +; X86-NEXT: movl %ecx, %edx +; X86-NEXT: orl %ebx, %edx +; X86-NEXT: orl %eax, %edx ; X86-NEXT: je .LBB8_1 ; X86-NEXT: # %bb.2: # %cond.false -; X86-NEXT: testl %ebp, %ebp +; X86-NEXT: testl %esi, %esi ; X86-NEXT: jne .LBB8_3 ; X86-NEXT: # %bb.4: # %cond.false -; X86-NEXT: bsrl %ebx, %edx -; X86-NEXT: xorl $31, %edx -; X86-NEXT: orl $32, %edx +; X86-NEXT: bsrl %ebx, %esi +; X86-NEXT: xorl $31, %esi +; X86-NEXT: orl $32, %esi ; X86-NEXT: testl %edi, %edi ; X86-NEXT: je .LBB8_7 ; X86-NEXT: .LBB8_6: -; X86-NEXT: bsrl %edi, %esi -; X86-NEXT: xorl $31, %esi +; X86-NEXT: bsrl %edi, %eax +; X86-NEXT: xorl $31, %eax ; X86-NEXT: jmp .LBB8_8 ; X86-NEXT: .LBB8_1: -; X86-NEXT: movl %ebx, %eax -; X86-NEXT: movl $0, (%esp) # 4-byte Folded Spill -; X86-NEXT: movl $128, %edx +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: movl $128, %esi ; X86-NEXT: jmp .LBB8_11 ; X86-NEXT: .LBB8_3: -; X86-NEXT: bsrl %ebp, %edx -; X86-NEXT: xorl $31, %edx +; X86-NEXT: bsrl %esi, %esi +; X86-NEXT: xorl $31, %esi ; X86-NEXT: testl %edi, %edi ; X86-NEXT: jne .LBB8_6 ; X86-NEXT: .LBB8_7: # %cond.false -; X86-NEXT: bsrl %ecx, %esi -; X86-NEXT: xorl $31, %esi -; X86-NEXT: orl $32, %esi +; X86-NEXT: bsrl %ecx, %eax +; X86-NEXT: xorl $31, %eax +; X86-NEXT: orl $32, %eax ; X86-NEXT: .LBB8_8: # %cond.false -; X86-NEXT: movl %ebx, %eax -; X86-NEXT: orl %ebp, %ebx +; X86-NEXT: movl %ebx, %edx +; X86-NEXT: orl 36(%ebp), %edx ; X86-NEXT: jne .LBB8_10 ; X86-NEXT: # %bb.9: # %cond.false -; X86-NEXT: orl $64, %esi -; X86-NEXT: movl %esi, %edx +; X86-NEXT: orl $64, %eax +; X86-NEXT: movl %eax, %esi ; X86-NEXT: .LBB8_10: # %cond.false -; X86-NEXT: movl $0, (%esp) # 4-byte Folded Spill +; X86-NEXT: xorl %eax, %eax ; X86-NEXT: .LBB8_11: # %cond.end -; X86-NEXT: xorl %esi, %esi ; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: orl %eax, %ecx -; X86-NEXT: orl %ebp, %edi +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: orl 32(%ebp), %ecx +; X86-NEXT: orl 36(%ebp), %edi ; X86-NEXT: orl %ecx, %edi ; X86-NEXT: je .LBB8_12 ; X86-NEXT: # %bb.13: # %cond.end -; X86-NEXT: xorl $127, %edx -; X86-NEXT: movl (%esp), %ecx # 4-byte Reload +; X86-NEXT: xorl $127, %esi +; X86-NEXT: movl %eax, %ecx ; X86-NEXT: jmp .LBB8_14 ; X86-NEXT: .LBB8_12: -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: movl 48(%ebp), %ebx +; X86-NEXT: movl 44(%ebp), %ecx +; X86-NEXT: movl 40(%ebp), %esi ; X86-NEXT: .LBB8_14: # %cond.end -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %ebx, 12(%eax) -; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %ebx, 8(%eax) ; X86-NEXT: movl %ecx, 4(%eax) -; X86-NEXT: movl %edx, (%eax) -; X86-NEXT: addl $4, %esp +; X86-NEXT: movl %esi, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -398,62 +399,67 @@ define i128 @cmov_bsr128_undef(i128 %x, i128 %y) nounwind { ; X86-LABEL: cmov_bsr128_undef: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: testl %edi, %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 28(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: testl %eax, %eax ; X86-NEXT: jne .LBB9_1 ; X86-NEXT: # %bb.2: -; X86-NEXT: bsrl %esi, %ecx -; X86-NEXT: xorl $31, %ecx -; X86-NEXT: orl $32, %ecx +; X86-NEXT: bsrl %edi, %esi +; X86-NEXT: xorl $31, %esi +; X86-NEXT: orl $32, %esi ; X86-NEXT: jmp .LBB9_3 ; X86-NEXT: .LBB9_1: -; X86-NEXT: bsrl %edi, %ecx -; X86-NEXT: xorl $31, %ecx +; X86-NEXT: bsrl %eax, %esi +; X86-NEXT: xorl $31, %esi ; X86-NEXT: .LBB9_3: -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl 24(%ebp), %ebx ; X86-NEXT: testl %edx, %edx ; X86-NEXT: jne .LBB9_4 ; X86-NEXT: # %bb.5: -; X86-NEXT: bsrl %ebx, %ebp -; X86-NEXT: xorl $31, %ebp -; X86-NEXT: orl $32, %ebp -; X86-NEXT: jmp .LBB9_6 +; X86-NEXT: bsrl %ebx, %ecx +; X86-NEXT: xorl $31, %ecx +; X86-NEXT: orl $32, %ecx +; X86-NEXT: orl %eax, %edi +; X86-NEXT: je .LBB9_7 +; X86-NEXT: jmp .LBB9_8 ; X86-NEXT: .LBB9_4: -; X86-NEXT: bsrl %edx, %ebp -; X86-NEXT: xorl $31, %ebp -; X86-NEXT: .LBB9_6: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: orl %edi, %esi +; X86-NEXT: bsrl %edx, %ecx +; X86-NEXT: xorl $31, %ecx +; X86-NEXT: orl %eax, %edi ; X86-NEXT: jne .LBB9_8 -; X86-NEXT: # %bb.7: -; X86-NEXT: orl $64, %ebp -; X86-NEXT: movl %ebp, %ecx +; X86-NEXT: .LBB9_7: +; X86-NEXT: orl $64, %ecx +; X86-NEXT: movl %ecx, %esi ; X86-NEXT: .LBB9_8: -; X86-NEXT: orl %edi, %edx -; X86-NEXT: orl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: orl %eax, %edx +; X86-NEXT: orl 32(%ebp), %ebx ; X86-NEXT: orl %edx, %ebx ; X86-NEXT: jne .LBB9_9 ; X86-NEXT: # %bb.10: -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl 52(%ebp), %edi +; X86-NEXT: movl 40(%ebp), %esi +; X86-NEXT: movl 44(%ebp), %ecx ; X86-NEXT: jmp .LBB9_11 ; X86-NEXT: .LBB9_9: -; X86-NEXT: xorl $127, %ecx +; X86-NEXT: xorl $127, %esi +; X86-NEXT: xorl %ecx, %ecx ; X86-NEXT: xorl %edx, %edx -; X86-NEXT: xorl %esi, %esi ; X86-NEXT: xorl %edi, %edi ; X86-NEXT: .LBB9_11: +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %esi, 8(%eax) -; X86-NEXT: movl %edx, 4(%eax) -; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %ecx, 4(%eax) +; X86-NEXT: movl %esi, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/bswap-wide-int.ll b/llvm/test/CodeGen/X86/bswap-wide-int.ll index 6d5e995a6d574..673b7f16de75c 100644 --- a/llvm/test/CodeGen/X86/bswap-wide-int.ll +++ b/llvm/test/CodeGen/X86/bswap-wide-int.ll @@ -41,13 +41,16 @@ define i64 @bswap_i64(i64 %a0) nounwind { define i128 @bswap_i128(i128 %a0) nounwind { ; X86-LABEL: bswap_i128: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %edi ; X86-NEXT: bswapl %edi ; X86-NEXT: bswapl %esi ; X86-NEXT: bswapl %edx @@ -56,25 +59,32 @@ define i128 @bswap_i128(i128 %a0) nounwind { ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edi, (%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X86-MOVBE-LABEL: bswap_i128: ; X86-MOVBE: # %bb.0: +; X86-MOVBE-NEXT: pushl %ebp +; X86-MOVBE-NEXT: movl %esp, %ebp ; X86-MOVBE-NEXT: pushl %edi ; X86-MOVBE-NEXT: pushl %esi -; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-MOVBE-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-MOVBE-NEXT: andl $-16, %esp +; X86-MOVBE-NEXT: movl 8(%ebp), %eax +; X86-MOVBE-NEXT: movl 32(%ebp), %ecx +; X86-MOVBE-NEXT: movl 36(%ebp), %edx +; X86-MOVBE-NEXT: movl 24(%ebp), %esi +; X86-MOVBE-NEXT: movl 28(%ebp), %edi ; X86-MOVBE-NEXT: movbel %esi, 12(%eax) ; X86-MOVBE-NEXT: movbel %edi, 8(%eax) ; X86-MOVBE-NEXT: movbel %ecx, 4(%eax) ; X86-MOVBE-NEXT: movbel %edx, (%eax) +; X86-MOVBE-NEXT: leal -8(%ebp), %esp ; X86-MOVBE-NEXT: popl %esi ; X86-MOVBE-NEXT: popl %edi +; X86-MOVBE-NEXT: popl %ebp ; X86-MOVBE-NEXT: retl $4 ; ; X64-LABEL: bswap_i128: diff --git a/llvm/test/CodeGen/X86/div-rem-pair-recomposition-signed.ll b/llvm/test/CodeGen/X86/div-rem-pair-recomposition-signed.ll index d869f8ec01a5a..455b72d16a075 100644 --- a/llvm/test/CodeGen/X86/div-rem-pair-recomposition-signed.ll +++ b/llvm/test/CodeGen/X86/div-rem-pair-recomposition-signed.ll @@ -152,17 +152,17 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp ; X86-NEXT: subl $176, %esp -; X86-NEXT: movl 20(%ebp), %edx -; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 36(%ebp), %ecx ; X86-NEXT: movl %ecx, %eax ; X86-NEXT: sarl $31, %eax ; X86-NEXT: xorl %eax, %ecx ; X86-NEXT: movl %ecx, %edi ; X86-NEXT: xorl %eax, %edx ; X86-NEXT: movl %edx, %esi -; X86-NEXT: movl 16(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %edx ; X86-NEXT: xorl %eax, %edx -; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %ecx ; X86-NEXT: xorl %eax, %ecx ; X86-NEXT: subl %eax, %ecx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill @@ -172,16 +172,15 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: sbbl %eax, %edi ; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 40(%ebp), %ecx -; X86-NEXT: movl %ecx, %edx +; X86-NEXT: movl 52(%ebp), %esi +; X86-NEXT: movl %esi, %edx ; X86-NEXT: sarl $31, %edx -; X86-NEXT: movl %ecx, %esi ; X86-NEXT: xorl %edx, %esi -; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 48(%ebp), %ecx ; X86-NEXT: xorl %edx, %ecx -; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: movl 44(%ebp), %ebx ; X86-NEXT: xorl %edx, %ebx -; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: movl 40(%ebp), %edi ; X86-NEXT: xorl %edx, %edi ; X86-NEXT: subl %edx, %edi ; X86-NEXT: sbbl %edx, %ebx @@ -204,45 +203,45 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: sete %al ; X86-NEXT: orb %cl, %al ; X86-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; X86-NEXT: bsrl %eax, %edx +; X86-NEXT: bsrl %esi, %edx ; X86-NEXT: xorl $31, %edx -; X86-NEXT: addl $32, %edx -; X86-NEXT: bsrl %esi, %ecx +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: bsrl %eax, %ecx ; X86-NEXT: xorl $31, %ecx +; X86-NEXT: orl $32, %ecx ; X86-NEXT: testl %esi, %esi -; X86-NEXT: cmovel %edx, %ecx +; X86-NEXT: cmovnel %edx, %ecx ; X86-NEXT: bsrl %ebx, %edx ; X86-NEXT: xorl $31, %edx ; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: bsrl %edi, %edi ; X86-NEXT: xorl $31, %edi -; X86-NEXT: addl $32, %edi +; X86-NEXT: orl $32, %edi ; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: testl %ebx, %ebx ; X86-NEXT: cmovnel %edx, %edi -; X86-NEXT: addl $64, %edi +; X86-NEXT: orl $64, %edi ; X86-NEXT: movl %eax, %edx ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: orl %esi, %edx ; X86-NEXT: cmovnel %ecx, %edi -; X86-NEXT: bsrl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload -; X86-NEXT: xorl $31, %edx -; X86-NEXT: addl $32, %edx ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; X86-NEXT: bsrl %eax, %ecx +; X86-NEXT: bsrl %eax, %edx +; X86-NEXT: xorl $31, %edx +; X86-NEXT: bsrl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload ; X86-NEXT: xorl $31, %ecx +; X86-NEXT: orl $32, %ecx ; X86-NEXT: testl %eax, %eax -; X86-NEXT: cmovel %edx, %ecx +; X86-NEXT: cmovnel %edx, %ecx ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload ; X86-NEXT: bsrl %ebx, %esi ; X86-NEXT: xorl $31, %esi ; X86-NEXT: bsrl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload ; X86-NEXT: xorl $31, %edx -; X86-NEXT: addl $32, %edx +; X86-NEXT: orl $32, %edx ; X86-NEXT: testl %ebx, %ebx ; X86-NEXT: cmovnel %esi, %edx -; X86-NEXT: addl $64, %edx +; X86-NEXT: orl $64, %edx ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload ; X86-NEXT: orl %eax, %esi ; X86-NEXT: cmovnel %ecx, %edx @@ -380,9 +379,9 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload ; X86-NEXT: adcl $-1, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; X86-NEXT: adcl $-1, %eax -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: adcl $-1, %ecx +; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload ; X86-NEXT: adcl $-1, %ecx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill @@ -488,13 +487,13 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: sbbl %ecx, %ebx ; X86-NEXT: sbbl %ecx, %esi ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 44(%ebp), %ecx +; X86-NEXT: movl 56(%ebp), %ecx ; X86-NEXT: movl %edx, (%ecx) ; X86-NEXT: movl %eax, 4(%ecx) ; X86-NEXT: movl %ebx, 8(%ecx) ; X86-NEXT: movl %esi, 12(%ecx) ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 28(%ebp), %ecx +; X86-NEXT: movl 40(%ebp), %ecx ; X86-NEXT: movl %ebx, %edi ; X86-NEXT: movl %edx, %esi ; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill @@ -508,7 +507,7 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: addl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload ; X86-NEXT: adcl $0, %ebx ; X86-NEXT: movl %esi, %eax -; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 44(%ebp), %esi ; X86-NEXT: mull %esi ; X86-NEXT: addl %ecx, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill @@ -523,17 +522,17 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: adcl %eax, %edx ; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload -; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl 40(%ebp), %eax ; X86-NEXT: imull %eax, %ebx ; X86-NEXT: mull %edi ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: imull %esi, %edi ; X86-NEXT: addl %edx, %edi ; X86-NEXT: addl %ebx, %edi -; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %eax ; X86-NEXT: movl %eax, %esi ; X86-NEXT: imull {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload -; X86-NEXT: movl 40(%ebp), %ebx +; X86-NEXT: movl 52(%ebp), %ebx ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload ; X86-NEXT: imull %edx, %ebx ; X86-NEXT: mull %edx @@ -543,13 +542,13 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: adcl %edi, %ebx ; X86-NEXT: addl %ecx, %eax ; X86-NEXT: adcl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload -; X86-NEXT: movl 12(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %edx ; X86-NEXT: subl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload -; X86-NEXT: movl 16(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %ecx ; X86-NEXT: sbbl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload -; X86-NEXT: movl 20(%ebp), %edi +; X86-NEXT: movl 32(%ebp), %edi ; X86-NEXT: sbbl %eax, %edi -; X86-NEXT: movl 24(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %esi ; X86-NEXT: sbbl %ebx, %esi ; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edx, (%eax) diff --git a/llvm/test/CodeGen/X86/div-rem-pair-recomposition-unsigned.ll b/llvm/test/CodeGen/X86/div-rem-pair-recomposition-unsigned.ll index 7bbddefd82721..adcfee5959af0 100644 --- a/llvm/test/CodeGen/X86/div-rem-pair-recomposition-unsigned.ll +++ b/llvm/test/CodeGen/X86/div-rem-pair-recomposition-unsigned.ll @@ -152,60 +152,60 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp ; X86-NEXT: subl $160, %esp -; X86-NEXT: movl 28(%ebp), %ebx -; X86-NEXT: movl 40(%ebp), %esi -; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: movl 40(%ebp), %ebx +; X86-NEXT: movl 52(%ebp), %esi +; X86-NEXT: movl 44(%ebp), %edi ; X86-NEXT: movl %edi, %eax ; X86-NEXT: orl %esi, %eax ; X86-NEXT: movl %ebx, %ecx -; X86-NEXT: orl 36(%ebp), %ecx +; X86-NEXT: orl 48(%ebp), %ecx ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: sete %cl -; X86-NEXT: movl 16(%ebp), %eax -; X86-NEXT: orl 24(%ebp), %eax -; X86-NEXT: movl 12(%ebp), %edx -; X86-NEXT: orl 20(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: orl 36(%ebp), %eax +; X86-NEXT: movl 24(%ebp), %edx +; X86-NEXT: orl 32(%ebp), %edx ; X86-NEXT: orl %eax, %edx ; X86-NEXT: sete %al ; X86-NEXT: orb %cl, %al ; X86-NEXT: movb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ; X86-NEXT: bsrl %esi, %edx ; X86-NEXT: xorl $31, %edx -; X86-NEXT: bsrl 36(%ebp), %ecx +; X86-NEXT: bsrl 48(%ebp), %ecx ; X86-NEXT: xorl $31, %ecx -; X86-NEXT: addl $32, %ecx +; X86-NEXT: orl $32, %ecx ; X86-NEXT: testl %esi, %esi ; X86-NEXT: cmovnel %edx, %ecx ; X86-NEXT: bsrl %edi, %edx ; X86-NEXT: xorl $31, %edx ; X86-NEXT: bsrl %ebx, %eax ; X86-NEXT: xorl $31, %eax -; X86-NEXT: addl $32, %eax +; X86-NEXT: orl $32, %eax ; X86-NEXT: testl %edi, %edi ; X86-NEXT: cmovnel %edx, %eax -; X86-NEXT: addl $64, %eax -; X86-NEXT: movl 36(%ebp), %edx +; X86-NEXT: orl $64, %eax +; X86-NEXT: movl 48(%ebp), %edx ; X86-NEXT: orl %esi, %edx ; X86-NEXT: cmovnel %ecx, %eax -; X86-NEXT: movl 24(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %ebx ; X86-NEXT: bsrl %ebx, %edx ; X86-NEXT: xorl $31, %edx -; X86-NEXT: movl 20(%ebp), %ecx +; X86-NEXT: movl 32(%ebp), %ecx ; X86-NEXT: bsrl %ecx, %ecx ; X86-NEXT: xorl $31, %ecx -; X86-NEXT: addl $32, %ecx +; X86-NEXT: orl $32, %ecx ; X86-NEXT: testl %ebx, %ebx ; X86-NEXT: cmovnel %edx, %ecx -; X86-NEXT: movl 16(%ebp), %edi +; X86-NEXT: movl 28(%ebp), %edi ; X86-NEXT: bsrl %edi, %esi ; X86-NEXT: xorl $31, %esi -; X86-NEXT: bsrl 12(%ebp), %edx +; X86-NEXT: bsrl 24(%ebp), %edx ; X86-NEXT: xorl $31, %edx -; X86-NEXT: addl $32, %edx +; X86-NEXT: orl $32, %edx ; X86-NEXT: testl %edi, %edi ; X86-NEXT: cmovnel %esi, %edx -; X86-NEXT: addl $64, %edx -; X86-NEXT: movl 20(%ebp), %edi +; X86-NEXT: orl $64, %edx +; X86-NEXT: movl 32(%ebp), %edi ; X86-NEXT: movl %edi, %esi ; X86-NEXT: orl %ebx, %esi ; X86-NEXT: cmovnel %ecx, %edx @@ -237,30 +237,30 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: sete %al ; X86-NEXT: testb %cl, %cl ; X86-NEXT: movb %cl, %ah -; X86-NEXT: movl 24(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %ebx ; X86-NEXT: movl $0, %esi ; X86-NEXT: cmovnel %esi, %ebx ; X86-NEXT: movl %edi, %ecx ; X86-NEXT: cmovnel %esi, %ecx ; X86-NEXT: movl $0, %edx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 16(%ebp), %esi +; X86-NEXT: movl 28(%ebp), %esi ; X86-NEXT: cmovnel %edx, %esi -; X86-NEXT: movl 12(%ebp), %edi +; X86-NEXT: movl 24(%ebp), %edi ; X86-NEXT: movl %edi, %ecx ; X86-NEXT: cmovnel %edx, %ecx ; X86-NEXT: orb %ah, %al -; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: movl 56(%ebp), %eax ; X86-NEXT: jne .LBB4_7 ; X86-NEXT: # %bb.1: # %udiv-bb1 ; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: xorps %xmm0, %xmm0 ; X86-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) -; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %eax ; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) -; X86-NEXT: movl 20(%ebp), %edx +; X86-NEXT: movl 32(%ebp), %edx ; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) -; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 36(%ebp), %eax ; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload ; X86-NEXT: movl %edx, %ecx @@ -289,7 +289,7 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload ; X86-NEXT: adcl $0, %esi ; X86-NEXT: adcl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill -; X86-NEXT: movl 20(%ebp), %ebx +; X86-NEXT: movl 32(%ebp), %ebx ; X86-NEXT: jae .LBB4_2 ; X86-NEXT: # %bb.5: ; X86-NEXT: xorl %edx, %edx @@ -299,13 +299,13 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: .LBB4_2: # %udiv-preheader ; X86-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 12(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %edx ; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) -; X86-NEXT: movl 16(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %edx ; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) ; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 36(%ebp), %eax ; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload ; X86-NEXT: # kill: def $al killed $al killed $eax @@ -334,16 +334,16 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: # kill: def $cl killed $cl killed $ecx ; X86-NEXT: shrdl %cl, %eax, %edi ; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl 40(%ebp), %eax ; X86-NEXT: addl $-1, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 32(%ebp), %eax +; X86-NEXT: movl 44(%ebp), %eax ; X86-NEXT: adcl $-1, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl 48(%ebp), %esi ; X86-NEXT: adcl $-1, %esi ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 40(%ebp), %eax +; X86-NEXT: movl 52(%ebp), %eax ; X86-NEXT: adcl $-1, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: xorl %eax, %eax @@ -391,13 +391,13 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: andl $1, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: andl 40(%ebp), %eax +; X86-NEXT: andl 52(%ebp), %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: andl 36(%ebp), %eax +; X86-NEXT: andl 48(%ebp), %eax ; X86-NEXT: movl %ecx, %edx -; X86-NEXT: andl 32(%ebp), %edx -; X86-NEXT: andl 28(%ebp), %ecx +; X86-NEXT: andl 44(%ebp), %edx +; X86-NEXT: andl 40(%ebp), %ecx ; X86-NEXT: subl %ecx, %ebx ; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload @@ -437,7 +437,7 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: orl %eax, %esi ; X86-NEXT: addl %ecx, %ecx ; X86-NEXT: orl %edx, %ecx -; X86-NEXT: movl 44(%ebp), %eax +; X86-NEXT: movl 56(%ebp), %eax ; X86-NEXT: .LBB4_7: # %udiv-end ; X86-NEXT: movl %ecx, (%eax) ; X86-NEXT: movl %esi, 4(%eax) @@ -446,23 +446,23 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: movl %ebx, 12(%eax) ; X86-NEXT: movl %esi, %edx ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %eax ; X86-NEXT: movl %eax, %esi ; X86-NEXT: imull %edx, %esi ; X86-NEXT: mull %ecx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: addl %esi, %edx -; X86-NEXT: movl 40(%ebp), %edi +; X86-NEXT: movl 52(%ebp), %edi ; X86-NEXT: imull %ecx, %edi ; X86-NEXT: addl %edx, %edi -; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl 40(%ebp), %eax ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload ; X86-NEXT: mull %esi ; X86-NEXT: movl %eax, %ecx -; X86-NEXT: imull 28(%ebp), %ebx +; X86-NEXT: imull 40(%ebp), %ebx ; X86-NEXT: addl %edx, %ebx -; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 44(%ebp), %edx ; X86-NEXT: imull %edx, %esi ; X86-NEXT: addl %ebx, %esi ; X86-NEXT: addl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload @@ -471,7 +471,7 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload ; X86-NEXT: movl %edi, %eax -; X86-NEXT: movl 28(%ebp), %ecx +; X86-NEXT: movl 40(%ebp), %ecx ; X86-NEXT: mull %ecx ; X86-NEXT: movl %edx, %esi ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill @@ -483,26 +483,26 @@ define i128 @scalar_i128(i128 %x, i128 %y, ptr %divdst) nounwind { ; X86-NEXT: adcl $0, %edx ; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl %edi, %eax -; X86-NEXT: mull 32(%ebp) -; X86-NEXT: movl 16(%ebp), %esi +; X86-NEXT: mull 44(%ebp) +; X86-NEXT: movl 28(%ebp), %esi ; X86-NEXT: movl %edx, %edi ; X86-NEXT: addl %ecx, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: adcl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload ; X86-NEXT: setb %cl ; X86-NEXT: movl %ebx, %eax -; X86-NEXT: mull 32(%ebp) +; X86-NEXT: mull 44(%ebp) ; X86-NEXT: addl %edi, %eax ; X86-NEXT: movzbl %cl, %ecx ; X86-NEXT: adcl %ecx, %edx ; X86-NEXT: addl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload ; X86-NEXT: adcl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload -; X86-NEXT: movl 12(%ebp), %ebx +; X86-NEXT: movl 24(%ebp), %ebx ; X86-NEXT: subl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload ; X86-NEXT: sbbl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload -; X86-NEXT: movl 20(%ebp), %edi +; X86-NEXT: movl 32(%ebp), %edi ; X86-NEXT: sbbl %eax, %edi -; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %ecx ; X86-NEXT: sbbl %edx, %ecx ; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %ebx, (%eax) diff --git a/llvm/test/CodeGen/X86/tail-dup-computed-goto.mir b/llvm/test/CodeGen/X86/early-tail-dup-computed-goto.mir similarity index 99% rename from llvm/test/CodeGen/X86/tail-dup-computed-goto.mir rename to llvm/test/CodeGen/X86/early-tail-dup-computed-goto.mir index 17de405928d37..3810e227bea95 100644 --- a/llvm/test/CodeGen/X86/tail-dup-computed-goto.mir +++ b/llvm/test/CodeGen/X86/early-tail-dup-computed-goto.mir @@ -1,6 +1,8 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 # RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=early-tailduplication -tail-dup-pred-size=1 -tail-dup-succ-size=1 %s -o - | FileCheck %s -# Check that only the computed goto is not be restrict by tail-dup-pred-size and tail-dup-succ-size. +# +# Check that only the computed goto and others are restricted by tail-dup-pred-size and tail-dup-succ-size. +# --- | @computed_goto.dispatch = constant [5 x ptr] [ptr null, ptr blockaddress(@computed_goto, %bb1), ptr blockaddress(@computed_goto, %bb2), ptr blockaddress(@computed_goto, %bb3), ptr blockaddress(@computed_goto, %bb4)] declare i64 @f0() diff --git a/llvm/test/CodeGen/X86/fp128-cast-strict.ll b/llvm/test/CodeGen/X86/fp128-cast-strict.ll index 707b05f3478db..bb5640aeb66fa 100644 --- a/llvm/test/CodeGen/X86/fp128-cast-strict.ll +++ b/llvm/test/CodeGen/X86/fp128-cast-strict.ll @@ -481,18 +481,21 @@ define i128 @fptosi_i128(fp128 %x) nounwind strictfp { ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $20, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __fixtfti -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -501,7 +504,7 @@ define i128 @fptosi_i128(fp128 %x) nounwind strictfp { ; X86-NEXT: movl %eax, (%esi) ; X86-NEXT: movl %ecx, 4(%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $20, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: retl $4 @@ -620,18 +623,21 @@ define i128 @fptoui_i128(fp128 %x) nounwind strictfp { ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $20, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __fixunstfti -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -640,7 +646,7 @@ define i128 @fptoui_i128(fp128 %x) nounwind strictfp { ; X86-NEXT: movl %eax, (%esi) ; X86-NEXT: movl %ecx, 4(%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $20, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: retl $4 @@ -818,18 +824,21 @@ define fp128 @sitofp_i128(i128 %x) nounwind strictfp { ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $20, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __floattitf -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -838,7 +847,7 @@ define fp128 @sitofp_i128(i128 %x) nounwind strictfp { ; X86-NEXT: movl %eax, (%esi) ; X86-NEXT: movl %ecx, 4(%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $20, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: retl $4 @@ -1016,18 +1025,21 @@ define fp128 @uitofp_i128(i128 %x) nounwind strictfp { ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $20, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __floatuntitf -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1036,7 +1048,7 @@ define fp128 @uitofp_i128(i128 %x) nounwind strictfp { ; X86-NEXT: movl %eax, (%esi) ; X86-NEXT: movl %ecx, 4(%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $20, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: retl $4 diff --git a/llvm/test/CodeGen/X86/fp128-cast.ll b/llvm/test/CodeGen/X86/fp128-cast.ll index 1de2484d47ba1..6d4ec063ccd46 100644 --- a/llvm/test/CodeGen/X86/fp128-cast.ll +++ b/llvm/test/CodeGen/X86/fp128-cast.ll @@ -415,16 +415,20 @@ define dso_local void @TestFPToSIF128_I128() nounwind { ; X86-LABEL: TestFPToSIF128_I128: ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %esi -; X86-NEXT: subl $36, %esp +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl vf128, %eax +; X86-NEXT: movl vf128+4, %ecx +; X86-NEXT: movl vf128+8, %edx +; X86-NEXT: movl vf128+12, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __fixtfti -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -432,7 +436,7 @@ define dso_local void @TestFPToSIF128_I128() nounwind { ; X86-NEXT: movl %edx, vi128+8 ; X86-NEXT: movl %ecx, vi128+4 ; X86-NEXT: movl %eax, vi128 -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $56, %esp ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -466,16 +470,20 @@ define dso_local void @TestFPToUIF128_U128() nounwind { ; X86-LABEL: TestFPToUIF128_U128: ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %esi -; X86-NEXT: subl $36, %esp +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl vf128, %eax +; X86-NEXT: movl vf128+4, %ecx +; X86-NEXT: movl vf128+8, %edx +; X86-NEXT: movl vf128+12, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __fixunstfti -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -483,7 +491,7 @@ define dso_local void @TestFPToUIF128_U128() nounwind { ; X86-NEXT: movl %edx, vu128+8 ; X86-NEXT: movl %ecx, vu128+4 ; X86-NEXT: movl %eax, vu128 -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $56, %esp ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -913,16 +921,20 @@ define dso_local void @TestSIToFPI128_F128() nounwind { ; X86-LABEL: TestSIToFPI128_F128: ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %esi -; X86-NEXT: subl $36, %esp +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl vi128, %eax +; X86-NEXT: movl vi128+4, %ecx +; X86-NEXT: movl vi128+8, %edx +; X86-NEXT: movl vi128+12, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl vi128+12 -; X86-NEXT: pushl vi128+8 -; X86-NEXT: pushl vi128+4 -; X86-NEXT: pushl vi128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __floattitf -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -930,7 +942,7 @@ define dso_local void @TestSIToFPI128_F128() nounwind { ; X86-NEXT: movl %edx, vf128+8 ; X86-NEXT: movl %ecx, vf128+4 ; X86-NEXT: movl %eax, vf128 -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $56, %esp ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -964,16 +976,20 @@ define dso_local void @TestUIToFPU128_F128() #2 { ; X86-LABEL: TestUIToFPU128_F128: ; X86: # %bb.0: # %entry ; X86-NEXT: pushl %esi -; X86-NEXT: subl $36, %esp +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl vu128, %eax +; X86-NEXT: movl vu128+4, %ecx +; X86-NEXT: movl vu128+8, %edx +; X86-NEXT: movl vu128+12, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl vu128+12 -; X86-NEXT: pushl vu128+8 -; X86-NEXT: pushl vu128+4 -; X86-NEXT: pushl vu128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __floatuntitf -; X86-NEXT: addl $28, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -981,7 +997,7 @@ define dso_local void @TestUIToFPU128_F128() #2 { ; X86-NEXT: movl %edx, vf128+8 ; X86-NEXT: movl %ecx, vf128+4 ; X86-NEXT: movl %eax, vf128 -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $56, %esp ; X86-NEXT: popl %esi ; X86-NEXT: retl ; @@ -1134,33 +1150,30 @@ define dso_local i32 @TestBits128(fp128 %ld) nounwind { ; ; X86-LABEL: TestBits128: ; X86: # %bb.0: # %entry -; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $20, %esp +; X86-NEXT: subl $72, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: subl $12, %esp -; X86-NEXT: leal {{[0-9]+}}(%esp), %edx -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %edx +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __multf3 -; X86-NEXT: addl $44, %esp +; X86-NEXT: subl $4, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: xorl %eax, %eax -; X86-NEXT: orl (%esp), %ecx +; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: sete %al -; X86-NEXT: addl $20, %esp +; X86-NEXT: addl $72, %esp ; X86-NEXT: popl %esi -; X86-NEXT: popl %edi ; X86-NEXT: retl ; ; X64-AVX-LABEL: TestBits128: @@ -1359,12 +1372,14 @@ define i1 @PR34866(i128 %x) nounwind { ; ; X86-LABEL: PR34866: ; X86: # %bb.0: +; X86-NEXT: subl $12, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl %ecx, %eax ; X86-NEXT: sete %al +; X86-NEXT: addl $12, %esp ; X86-NEXT: retl ; ; X64-AVX-LABEL: PR34866: @@ -1394,12 +1409,14 @@ define i1 @PR34866_commute(i128 %x) nounwind { ; ; X86-LABEL: PR34866_commute: ; X86: # %bb.0: +; X86-NEXT: subl $12, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl %ecx, %eax ; X86-NEXT: sete %al +; X86-NEXT: addl $12, %esp ; X86-NEXT: retl ; ; X64-AVX-LABEL: PR34866_commute: diff --git a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll index a7eea04181f60..ad2d690fd7ed0 100644 --- a/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll +++ b/llvm/test/CodeGen/X86/fp128-libcalls-strict.ll @@ -41,27 +41,40 @@ define fp128 @add(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: add: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __addtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: add: @@ -81,24 +94,32 @@ define fp128 @add(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___addtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -107,9 +128,10 @@ define fp128 @add(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -141,27 +163,40 @@ define fp128 @sub(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: sub: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __subtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: sub: @@ -181,24 +216,32 @@ define fp128 @sub(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___subtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -207,9 +250,10 @@ define fp128 @sub(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -241,27 +285,40 @@ define fp128 @mul(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: mul: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __multf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: mul: @@ -281,24 +338,32 @@ define fp128 @mul(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___multf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -307,9 +372,10 @@ define fp128 @mul(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -341,27 +407,40 @@ define fp128 @div(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: div: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __divtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: div: @@ -381,24 +460,32 @@ define fp128 @div(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___divtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -407,9 +494,10 @@ define fp128 @div(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -434,31 +522,48 @@ define fp128 @fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp { ; ; X86-LABEL: fma: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $92, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmaf128 -; X86-NEXT: addl $60, %esp -; X86-NEXT: movaps (%esp), %xmm0 -; X86-NEXT: movaps %xmm0, (%esi) -; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 +; X86-NEXT: movaps %xmm0, (%ebp) +; X86-NEXT: movl %ebp, %eax +; X86-NEXT: addl $92, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: fma: @@ -481,28 +586,40 @@ define fp128 @fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $96, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 56(%ebp) -; WIN-X86-NEXT: pushl 52(%ebp) -; WIN-X86-NEXT: pushl 48(%ebp) -; WIN-X86-NEXT: pushl 44(%ebp) -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 52(%ebp), %ebx +; WIN-X86-NEXT: movl 56(%ebp), %edi +; WIN-X86-NEXT: movl 60(%ebp), %edx +; WIN-X86-NEXT: movl 64(%ebp), %ecx +; WIN-X86-NEXT: movl 68(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 48(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 44(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 40(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmal -; WIN-X86-NEXT: addl $52, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -511,9 +628,10 @@ define fp128 @fma(fp128 %x, fp128 %y, fp128 %z) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -538,27 +656,40 @@ define fp128 @frem(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: frem: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmodf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: frem: @@ -578,24 +709,32 @@ define fp128 @frem(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmodl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -604,9 +743,10 @@ define fp128 @frem(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -631,23 +771,28 @@ define fp128 @ceil(fp128 %x) nounwind strictfp { ; ; X86-LABEL: ceil: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll ceilf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: ceil: @@ -667,17 +812,20 @@ define fp128 @ceil(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _ceill -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -713,23 +861,28 @@ define fp128 @acos(fp128 %x) nounwind strictfp { ; ; X86-LABEL: acos: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll acosf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: acos: @@ -749,17 +902,20 @@ define fp128 @acos(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _acosl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -795,23 +951,28 @@ define fp128 @cos(fp128 %x) nounwind strictfp { ; ; X86-LABEL: cos: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll cosf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: cos: @@ -831,17 +992,20 @@ define fp128 @cos(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _cosl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -877,23 +1041,28 @@ define fp128 @cosh(fp128 %x) nounwind strictfp { ; ; X86-LABEL: cosh: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll coshf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: cosh: @@ -913,17 +1082,20 @@ define fp128 @cosh(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _coshl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -959,23 +1131,28 @@ define fp128 @exp(fp128 %x) nounwind strictfp { ; ; X86-LABEL: exp: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll expf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: exp: @@ -995,17 +1172,20 @@ define fp128 @exp(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _expl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1041,23 +1221,28 @@ define fp128 @exp2(fp128 %x) nounwind strictfp { ; ; X86-LABEL: exp2: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll exp2f128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: exp2: @@ -1077,17 +1262,20 @@ define fp128 @exp2(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _exp2l -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1123,23 +1311,28 @@ define fp128 @floor(fp128 %x) nounwind strictfp { ; ; X86-LABEL: floor: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll floorf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: floor: @@ -1159,17 +1352,20 @@ define fp128 @floor(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _floorl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1205,23 +1401,28 @@ define fp128 @log(fp128 %x) nounwind strictfp { ; ; X86-LABEL: log: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll logf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: log: @@ -1241,17 +1442,20 @@ define fp128 @log(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _logl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1287,23 +1491,28 @@ define fp128 @log10(fp128 %x) nounwind strictfp { ; ; X86-LABEL: log10: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll log10f128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: log10: @@ -1323,17 +1532,20 @@ define fp128 @log10(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _log10l -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1369,23 +1581,28 @@ define fp128 @log2(fp128 %x) nounwind strictfp { ; ; X86-LABEL: log2: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll log2f128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: log2: @@ -1405,17 +1622,20 @@ define fp128 @log2(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _log2l -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1451,27 +1671,40 @@ define fp128 @maxnum(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: maxnum: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmaxf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: maxnum: @@ -1491,24 +1724,32 @@ define fp128 @maxnum(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmaxl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1517,9 +1758,10 @@ define fp128 @maxnum(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1544,27 +1786,40 @@ define fp128 @minnum(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: minnum: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fminf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: minnum: @@ -1584,24 +1839,32 @@ define fp128 @minnum(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fminl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1610,9 +1873,10 @@ define fp128 @minnum(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1637,23 +1901,28 @@ define fp128 @nearbyint(fp128 %x) nounwind strictfp { ; ; X86-LABEL: nearbyint: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll nearbyintf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: nearbyint: @@ -1673,17 +1942,20 @@ define fp128 @nearbyint(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _nearbyintl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1719,27 +1991,40 @@ define fp128 @pow(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: pow: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll powf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: pow: @@ -1759,24 +2044,32 @@ define fp128 @pow(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _powl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1785,9 +2078,10 @@ define fp128 @pow(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1819,24 +2113,32 @@ define fp128 @powi(fp128 %x, i32 %y) nounwind strictfp { ; ; X86-LABEL: powi: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $64, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $8, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __powitf2 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $64, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx ; X86-NEXT: retl $4 ; ; WIN-LABEL: powi: @@ -1853,21 +2155,26 @@ define fp128 @powi(fp128 %x, i32 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___powitf2 -; WIN-X86-NEXT: addl $24, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1876,9 +2183,10 @@ define fp128 @powi(fp128 %x, i32 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1903,23 +2211,28 @@ define fp128 @rint(fp128 %x) nounwind strictfp { ; ; X86-LABEL: rint: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll rintf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: rint: @@ -1939,17 +2252,20 @@ define fp128 @rint(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _rintl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1985,23 +2301,28 @@ define fp128 @round(fp128 %x) nounwind strictfp { ; ; X86-LABEL: round: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll roundf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: round: @@ -2021,17 +2342,20 @@ define fp128 @round(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _roundl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2067,23 +2391,28 @@ define fp128 @roundeven(fp128 %x) nounwind strictfp { ; ; X86-LABEL: roundeven: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll roundevenf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: roundeven: @@ -2103,17 +2432,20 @@ define fp128 @roundeven(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _roundevenl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2149,23 +2481,28 @@ define fp128 @asin(fp128 %x) nounwind strictfp { ; ; X86-LABEL: asin: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll asinf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: asin: @@ -2185,17 +2522,20 @@ define fp128 @asin(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _asinl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2231,23 +2571,28 @@ define fp128 @sin(fp128 %x) nounwind strictfp { ; ; X86-LABEL: sin: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sinf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: sin: @@ -2267,17 +2612,20 @@ define fp128 @sin(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sinl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2313,23 +2661,28 @@ define fp128 @sinh(fp128 %x) nounwind strictfp { ; ; X86-LABEL: sinh: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sinhf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: sinh: @@ -2349,17 +2702,20 @@ define fp128 @sinh(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sinhl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2395,23 +2751,28 @@ define fp128 @sqrt(fp128 %x) nounwind strictfp { ; ; X86-LABEL: sqrt: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sqrtf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: sqrt: @@ -2431,17 +2792,20 @@ define fp128 @sqrt(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sqrtl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2477,23 +2841,28 @@ define fp128 @atan(fp128 %x) nounwind strictfp { ; ; X86-LABEL: atan: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll atanf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: atan: @@ -2513,17 +2882,20 @@ define fp128 @atan(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _atanl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2559,27 +2931,40 @@ define fp128 @atan2(fp128 %x, fp128 %y) nounwind strictfp { ; ; X86-LABEL: atan2: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll atan2f128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: atan2: @@ -2599,24 +2984,32 @@ define fp128 @atan2(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _atan2l -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2625,9 +3018,10 @@ define fp128 @atan2(fp128 %x, fp128 %y) nounwind strictfp { ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -2652,23 +3046,28 @@ define fp128 @tan(fp128 %x) nounwind strictfp { ; ; X86-LABEL: tan: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll tanf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: tan: @@ -2688,17 +3087,20 @@ define fp128 @tan(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _tanl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2734,23 +3136,28 @@ define fp128 @tanh(fp128 %x) nounwind strictfp { ; ; X86-LABEL: tanh: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll tanhf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: tanh: @@ -2770,17 +3177,20 @@ define fp128 @tanh(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _tanhl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2816,23 +3226,28 @@ define fp128 @trunc(fp128 %x) nounwind strictfp { ; ; X86-LABEL: trunc: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll truncf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: trunc: @@ -2852,17 +3267,20 @@ define fp128 @trunc(fp128 %x) nounwind strictfp { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _truncl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2919,12 +3337,18 @@ define i32 @lrint(fp128 %x) nounwind strictfp { ; ; WIN-X86-LABEL: lrint: ; WIN-X86: # %bb.0: # %entry -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 20(%ebp) +; WIN-X86-NEXT: pushl 16(%ebp) +; WIN-X86-NEXT: pushl 12(%ebp) +; WIN-X86-NEXT: pushl 8(%ebp) ; WIN-X86-NEXT: calll _lrintl ; WIN-X86-NEXT: addl $16, %esp +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: %rint = call i32 @llvm.experimental.constrained.lrint.i32.f128(fp128 %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -2969,12 +3393,18 @@ define i64 @llrint(fp128 %x) nounwind strictfp { ; ; WIN-X86-LABEL: llrint: ; WIN-X86: # %bb.0: # %entry -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 20(%ebp) +; WIN-X86-NEXT: pushl 16(%ebp) +; WIN-X86-NEXT: pushl 12(%ebp) +; WIN-X86-NEXT: pushl 8(%ebp) ; WIN-X86-NEXT: calll _llrintl ; WIN-X86-NEXT: addl $16, %esp +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: %rint = call i64 @llvm.experimental.constrained.llrint.i64.f128(fp128 %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -3019,12 +3449,18 @@ define i32 @lround(fp128 %x) nounwind strictfp { ; ; WIN-X86-LABEL: lround: ; WIN-X86: # %bb.0: # %entry -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 20(%ebp) +; WIN-X86-NEXT: pushl 16(%ebp) +; WIN-X86-NEXT: pushl 12(%ebp) +; WIN-X86-NEXT: pushl 8(%ebp) ; WIN-X86-NEXT: calll _lroundl ; WIN-X86-NEXT: addl $16, %esp +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: %round = call i32 @llvm.experimental.constrained.lround.i32.f128(fp128 %x, metadata !"fpexcept.strict") #0 @@ -3069,12 +3505,18 @@ define i64 @llround(fp128 %x) nounwind strictfp { ; ; WIN-X86-LABEL: llround: ; WIN-X86: # %bb.0: # %entry -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 20(%ebp) +; WIN-X86-NEXT: pushl 16(%ebp) +; WIN-X86-NEXT: pushl 12(%ebp) +; WIN-X86-NEXT: pushl 8(%ebp) ; WIN-X86-NEXT: calll _llroundl ; WIN-X86-NEXT: addl $16, %esp +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: %round = call i64 @llvm.experimental.constrained.llround.i64.f128(fp128 %x, metadata !"fpexcept.strict") #0 @@ -3176,26 +3618,32 @@ define i64 @cmp(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 { ; ; WIN-X86-LABEL: cmp: ; WIN-X86: # %bb.0: -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) +; WIN-X86-NEXT: pushl 36(%ebp) +; WIN-X86-NEXT: pushl 32(%ebp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___eqtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: testl %eax, %eax ; WIN-X86-NEXT: je LBB37_1 ; WIN-X86-NEXT: # %bb.2: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 16(%ebp), %ecx ; WIN-X86-NEXT: jmp LBB37_3 ; WIN-X86-NEXT: LBB37_1: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 8(%ebp), %ecx ; WIN-X86-NEXT: LBB37_3: ; WIN-X86-NEXT: movl (%ecx), %eax ; WIN-X86-NEXT: movl 4(%ecx), %edx +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl %cond = call i1 @llvm.experimental.constrained.fcmp.f128( fp128 %x, fp128 %y, @@ -3300,26 +3748,32 @@ define i64 @cmps(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 { ; ; WIN-X86-LABEL: cmps: ; WIN-X86: # %bb.0: -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) +; WIN-X86-NEXT: pushl 36(%ebp) +; WIN-X86-NEXT: pushl 32(%ebp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___eqtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: testl %eax, %eax ; WIN-X86-NEXT: je LBB38_1 ; WIN-X86-NEXT: # %bb.2: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 16(%ebp), %ecx ; WIN-X86-NEXT: jmp LBB38_3 ; WIN-X86-NEXT: LBB38_1: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 8(%ebp), %ecx ; WIN-X86-NEXT: LBB38_3: ; WIN-X86-NEXT: movl (%ecx), %eax ; WIN-X86-NEXT: movl 4(%ecx), %edx +; WIN-X86-NEXT: movl %ebp, %esp +; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl %cond = call i1 @llvm.experimental.constrained.fcmps.f128( fp128 %x, fp128 %y, @@ -3496,44 +3950,47 @@ define i64 @cmp_ueq_q(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 { ; WIN-X86-LABEL: cmp_ueq_q: ; WIN-X86: # %bb.0: ; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: movl 32(%ebp), %edi +; WIN-X86-NEXT: movl 36(%ebp), %esi +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: pushl %edi -; WIN-X86-NEXT: pushl %ebp -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___eqtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: testl %eax, %eax ; WIN-X86-NEXT: sete %bl -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: pushl %edi -; WIN-X86-NEXT: pushl %ebp -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___unordtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: orb %bl, %al ; WIN-X86-NEXT: jne LBB39_1 ; WIN-X86-NEXT: # %bb.2: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 16(%ebp), %ecx ; WIN-X86-NEXT: jmp LBB39_3 ; WIN-X86-NEXT: LBB39_1: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 8(%ebp), %ecx ; WIN-X86-NEXT: LBB39_3: ; WIN-X86-NEXT: movl (%ecx), %eax ; WIN-X86-NEXT: movl 4(%ecx), %edx +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi ; WIN-X86-NEXT: popl %ebx @@ -3716,32 +4173,34 @@ define i64 @cmp_one_q(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 { ; WIN-X86-LABEL: cmp_one_q: ; WIN-X86: # %bb.0: ; WIN-X86-NEXT: pushl %ebp +; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: andl $-16, %esp +; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: movl 32(%ebp), %edi +; WIN-X86-NEXT: movl 36(%ebp), %esi +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: pushl %edi -; WIN-X86-NEXT: pushl %ebp -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___eqtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: testl %eax, %eax ; WIN-X86-NEXT: setne %bl -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 52(%ebp) +; WIN-X86-NEXT: pushl 48(%ebp) +; WIN-X86-NEXT: pushl 44(%ebp) +; WIN-X86-NEXT: pushl 40(%ebp) ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: pushl %edi -; WIN-X86-NEXT: pushl %ebp -; WIN-X86-NEXT: pushl {{[0-9]+}}(%esp) +; WIN-X86-NEXT: pushl 28(%ebp) +; WIN-X86-NEXT: pushl 24(%ebp) ; WIN-X86-NEXT: calll ___unordtf2 ; WIN-X86-NEXT: addl $32, %esp ; WIN-X86-NEXT: testl %eax, %eax @@ -3749,13 +4208,14 @@ define i64 @cmp_one_q(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 { ; WIN-X86-NEXT: testb %bl, %al ; WIN-X86-NEXT: jne LBB40_1 ; WIN-X86-NEXT: # %bb.2: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 16(%ebp), %ecx ; WIN-X86-NEXT: jmp LBB40_3 ; WIN-X86-NEXT: LBB40_1: -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; WIN-X86-NEXT: leal 8(%ebp), %ecx ; WIN-X86-NEXT: LBB40_3: ; WIN-X86-NEXT: movl (%ecx), %eax ; WIN-X86-NEXT: movl 4(%ecx), %edx +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi ; WIN-X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/fp128-libcalls.ll b/llvm/test/CodeGen/X86/fp128-libcalls.ll index f727a79078627..4b0449fd7502e 100644 --- a/llvm/test/CodeGen/X86/fp128-libcalls.ll +++ b/llvm/test/CodeGen/X86/fp128-libcalls.ll @@ -42,22 +42,38 @@ define dso_local void @Test128Add(fp128 %d1, fp128 %d2) nounwind { ; ; X86-LABEL: Test128Add: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __addtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128Add: @@ -78,22 +94,31 @@ define dso_local void @Test128Add(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %edi +; WIN-X86-NEXT: movl 28(%ebp), %ebx +; WIN-X86-NEXT: movl 32(%ebp), %ecx +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___addtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -101,8 +126,10 @@ define dso_local void @Test128Add(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+8 ; WIN-X86-NEXT: movl %ecx, _vf128+4 ; WIN-X86-NEXT: movl %eax, _vf128 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -144,22 +171,38 @@ define dso_local void @Test128_1Add(fp128 %d1) nounwind { ; ; X86-LABEL: Test128_1Add: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl vf128, %edi +; X86-NEXT: movl vf128+4, %ebx +; X86-NEXT: movl vf128+8, %ebp +; X86-NEXT: movl vf128+12, %eax +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __addtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128_1Add: @@ -180,22 +223,31 @@ define dso_local void @Test128_1Add(fp128 %d1) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl _vf128+12 -; WIN-X86-NEXT: pushl _vf128+8 -; WIN-X86-NEXT: pushl _vf128+4 -; WIN-X86-NEXT: pushl _vf128 -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %esi +; WIN-X86-NEXT: movl 20(%ebp), %edi +; WIN-X86-NEXT: movl _vf128, %edx +; WIN-X86-NEXT: movl _vf128+4, %ebx +; WIN-X86-NEXT: movl _vf128+8, %ecx +; WIN-X86-NEXT: movl _vf128+12, %eax +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___addtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -203,8 +255,10 @@ define dso_local void @Test128_1Add(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+12 ; WIN-X86-NEXT: movl %eax, _vf128 ; WIN-X86-NEXT: movl %ecx, _vf128+4 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -241,22 +295,38 @@ define dso_local void @Test128Sub(fp128 %d1, fp128 %d2) nounwind { ; ; X86-LABEL: Test128Sub: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __subtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128Sub: @@ -277,22 +347,31 @@ define dso_local void @Test128Sub(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %edi +; WIN-X86-NEXT: movl 28(%ebp), %ebx +; WIN-X86-NEXT: movl 32(%ebp), %ecx +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___subtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -300,8 +379,10 @@ define dso_local void @Test128Sub(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+8 ; WIN-X86-NEXT: movl %ecx, _vf128+4 ; WIN-X86-NEXT: movl %eax, _vf128 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -343,22 +424,38 @@ define dso_local void @Test128_1Sub(fp128 %d1) nounwind { ; ; X86-LABEL: Test128_1Sub: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl vf128, %edi +; X86-NEXT: movl vf128+4, %ebx +; X86-NEXT: movl vf128+8, %ebp +; X86-NEXT: movl vf128+12, %eax +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __subtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128_1Sub: @@ -379,22 +476,31 @@ define dso_local void @Test128_1Sub(fp128 %d1) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl _vf128+12 -; WIN-X86-NEXT: pushl _vf128+8 -; WIN-X86-NEXT: pushl _vf128+4 -; WIN-X86-NEXT: pushl _vf128 -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %esi +; WIN-X86-NEXT: movl 20(%ebp), %edi +; WIN-X86-NEXT: movl _vf128, %edx +; WIN-X86-NEXT: movl _vf128+4, %ebx +; WIN-X86-NEXT: movl _vf128+8, %ecx +; WIN-X86-NEXT: movl _vf128+12, %eax +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___subtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -402,8 +508,10 @@ define dso_local void @Test128_1Sub(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+12 ; WIN-X86-NEXT: movl %eax, _vf128 ; WIN-X86-NEXT: movl %ecx, _vf128+4 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -440,22 +548,38 @@ define dso_local void @Test128Mul(fp128 %d1, fp128 %d2) nounwind { ; ; X86-LABEL: Test128Mul: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __multf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128Mul: @@ -476,22 +600,31 @@ define dso_local void @Test128Mul(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %edi +; WIN-X86-NEXT: movl 28(%ebp), %ebx +; WIN-X86-NEXT: movl 32(%ebp), %ecx +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___multf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -499,8 +632,10 @@ define dso_local void @Test128Mul(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+8 ; WIN-X86-NEXT: movl %ecx, _vf128+4 ; WIN-X86-NEXT: movl %eax, _vf128 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -542,22 +677,38 @@ define dso_local void @Test128_1Mul(fp128 %d1) nounwind { ; ; X86-LABEL: Test128_1Mul: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl vf128, %edi +; X86-NEXT: movl vf128+4, %ebx +; X86-NEXT: movl vf128+8, %ebp +; X86-NEXT: movl vf128+12, %eax +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __multf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128_1Mul: @@ -578,22 +729,31 @@ define dso_local void @Test128_1Mul(fp128 %d1) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl _vf128+12 -; WIN-X86-NEXT: pushl _vf128+8 -; WIN-X86-NEXT: pushl _vf128+4 -; WIN-X86-NEXT: pushl _vf128 -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %esi +; WIN-X86-NEXT: movl 20(%ebp), %edi +; WIN-X86-NEXT: movl _vf128, %edx +; WIN-X86-NEXT: movl _vf128+4, %ebx +; WIN-X86-NEXT: movl _vf128+8, %ecx +; WIN-X86-NEXT: movl _vf128+12, %eax +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___multf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -601,8 +761,10 @@ define dso_local void @Test128_1Mul(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+12 ; WIN-X86-NEXT: movl %eax, _vf128 ; WIN-X86-NEXT: movl %ecx, _vf128+4 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -639,22 +801,38 @@ define dso_local void @Test128Div(fp128 %d1, fp128 %d2) nounwind { ; ; X86-LABEL: Test128Div: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __divtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128Div: @@ -675,22 +853,31 @@ define dso_local void @Test128Div(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %edi +; WIN-X86-NEXT: movl 28(%ebp), %ebx +; WIN-X86-NEXT: movl 32(%ebp), %ecx +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___divtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -698,8 +885,10 @@ define dso_local void @Test128Div(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+8 ; WIN-X86-NEXT: movl %ecx, _vf128+4 ; WIN-X86-NEXT: movl %eax, _vf128 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -741,22 +930,38 @@ define dso_local void @Test128_1Div(fp128 %d1) nounwind { ; ; X86-LABEL: Test128_1Div: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl vf128, %edi +; X86-NEXT: movl vf128+4, %ebx +; X86-NEXT: movl vf128+8, %ebp +; X86-NEXT: movl vf128+12, %eax +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll __divtf3 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128_1Div: @@ -777,22 +982,31 @@ define dso_local void @Test128_1Div(fp128 %d1) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl _vf128+12 -; WIN-X86-NEXT: pushl _vf128+8 -; WIN-X86-NEXT: pushl _vf128+4 -; WIN-X86-NEXT: pushl _vf128 -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %esi +; WIN-X86-NEXT: movl 20(%ebp), %edi +; WIN-X86-NEXT: movl _vf128, %edx +; WIN-X86-NEXT: movl _vf128+4, %ebx +; WIN-X86-NEXT: movl _vf128+8, %ecx +; WIN-X86-NEXT: movl _vf128+12, %eax +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll ___divtf3 -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -800,8 +1014,10 @@ define dso_local void @Test128_1Div(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+12 ; WIN-X86-NEXT: movl %eax, _vf128 ; WIN-X86-NEXT: movl %ecx, _vf128+4 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -830,22 +1046,38 @@ define dso_local void @Test128Rem(fp128 %d1, fp128 %d2) nounwind { ; ; X86-LABEL: Test128Rem: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmodf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128Rem: @@ -866,22 +1098,31 @@ define dso_local void @Test128Rem(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %edi +; WIN-X86-NEXT: movl 28(%ebp), %ebx +; WIN-X86-NEXT: movl 32(%ebp), %ecx +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmodl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -889,8 +1130,10 @@ define dso_local void @Test128Rem(fp128 %d1, fp128 %d2) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+8 ; WIN-X86-NEXT: movl %ecx, _vf128+4 ; WIN-X86-NEXT: movl %eax, _vf128 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -922,22 +1165,38 @@ define dso_local void @Test128_1Rem(fp128 %d1) nounwind { ; ; X86-LABEL: Test128_1Rem: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: subl $76, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl vf128, %edi +; X86-NEXT: movl vf128+4, %ebx +; X86-NEXT: movl vf128+8, %ebp +; X86-NEXT: movl vf128+12, %eax +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl vf128+12 -; X86-NEXT: pushl vf128+8 -; X86-NEXT: pushl vf128+4 -; X86-NEXT: pushl vf128 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmodf128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $76, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; WIN-LABEL: Test128_1Rem: @@ -958,22 +1217,31 @@ define dso_local void @Test128_1Rem(fp128 %d1) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx +; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl _vf128+12 -; WIN-X86-NEXT: pushl _vf128+8 -; WIN-X86-NEXT: pushl _vf128+4 -; WIN-X86-NEXT: pushl _vf128 -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $80, %esp +; WIN-X86-NEXT: movl 16(%ebp), %esi +; WIN-X86-NEXT: movl 20(%ebp), %edi +; WIN-X86-NEXT: movl _vf128, %edx +; WIN-X86-NEXT: movl _vf128+4, %ebx +; WIN-X86-NEXT: movl _vf128+8, %ecx +; WIN-X86-NEXT: movl _vf128+12, %eax +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 12(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmodl -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -981,8 +1249,10 @@ define dso_local void @Test128_1Rem(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %edx, _vf128+12 ; WIN-X86-NEXT: movl %eax, _vf128 ; WIN-X86-NEXT: movl %ecx, _vf128+4 -; WIN-X86-NEXT: leal -4(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi +; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1011,18 +1281,24 @@ define dso_local void @Test128Sqrt(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Sqrt: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sqrtf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Sqrt: @@ -1042,16 +1318,19 @@ define dso_local void @Test128Sqrt(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sqrtl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1089,18 +1368,24 @@ define dso_local void @Test128Sin(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Sin: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sinf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Sin: @@ -1120,16 +1405,19 @@ define dso_local void @Test128Sin(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sinl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1167,18 +1455,24 @@ define dso_local void @Test128Cos(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Cos: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll cosf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Cos: @@ -1198,16 +1492,19 @@ define dso_local void @Test128Cos(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _cosl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1245,18 +1542,24 @@ define dso_local void @Test128Ceil(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Ceil: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll ceilf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Ceil: @@ -1276,16 +1579,19 @@ define dso_local void @Test128Ceil(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _ceill -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1323,18 +1629,24 @@ define dso_local void @Test128Floor(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Floor: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll floorf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Floor: @@ -1354,16 +1666,19 @@ define dso_local void @Test128Floor(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _floorl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1401,18 +1716,24 @@ define dso_local void @Test128Trunc(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Trunc: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll truncf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Trunc: @@ -1432,16 +1753,19 @@ define dso_local void @Test128Trunc(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _truncl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1479,18 +1803,24 @@ define dso_local void @Test128Nearbyint(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Nearbyint: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll nearbyintf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Nearbyint: @@ -1510,16 +1840,19 @@ define dso_local void @Test128Nearbyint(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _nearbyintl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1557,18 +1890,24 @@ define dso_local void @Test128Rint(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Rint: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll rintf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Rint: @@ -1588,16 +1927,19 @@ define dso_local void @Test128Rint(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _rintl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1635,18 +1977,24 @@ define dso_local void @Test128Round(fp128 %d1) nounwind { ; ; X86-LABEL: Test128Round: ; X86: # %bb.0: # %entry -; X86-NEXT: subl $40, %esp +; X86-NEXT: pushl %esi +; X86-NEXT: subl $56, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll roundf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, vf128 -; X86-NEXT: addl $28, %esp +; X86-NEXT: addl $56, %esp +; X86-NEXT: popl %esi ; X86-NEXT: retl ; ; WIN-LABEL: Test128Round: @@ -1666,16 +2014,19 @@ define dso_local void @Test128Round(fp128 %d1) nounwind { ; WIN-X86-NEXT: movl %esp, %ebp ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $32, %esp -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl 8(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: movl 8(%ebp), %eax +; WIN-X86-NEXT: movl 12(%ebp), %ecx +; WIN-X86-NEXT: movl 16(%ebp), %edx +; WIN-X86-NEXT: movl 20(%ebp), %esi +; WIN-X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _roundl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %esi @@ -1705,31 +2056,48 @@ define fp128 @Test128FMA(fp128 %a, fp128 %b, fp128 %c) nounwind { ; ; X86-LABEL: Test128FMA: ; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $92, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll fmaf128 -; X86-NEXT: addl $60, %esp -; X86-NEXT: movaps (%esp), %xmm0 -; X86-NEXT: movaps %xmm0, (%esi) -; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 +; X86-NEXT: movaps %xmm0, (%ebp) +; X86-NEXT: movl %ebp, %eax +; X86-NEXT: addl $92, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128FMA: @@ -1752,28 +2120,40 @@ define fp128 @Test128FMA(fp128 %a, fp128 %b, fp128 %c) nounwind { ; WIN-X86: # %bb.0: # %entry ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $96, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 56(%ebp) -; WIN-X86-NEXT: pushl 52(%ebp) -; WIN-X86-NEXT: pushl 48(%ebp) -; WIN-X86-NEXT: pushl 44(%ebp) -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 52(%ebp), %ebx +; WIN-X86-NEXT: movl 56(%ebp), %edi +; WIN-X86-NEXT: movl 60(%ebp), %edx +; WIN-X86-NEXT: movl 64(%ebp), %ecx +; WIN-X86-NEXT: movl 68(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 48(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 44(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 40(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 36(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _fmal -; WIN-X86-NEXT: addl $52, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1782,9 +2162,10 @@ define fp128 @Test128FMA(fp128 %a, fp128 %b, fp128 %c) nounwind { ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl entry: @@ -1804,23 +2185,28 @@ define fp128 @Test128Acos(fp128 %a) nounwind { ; ; X86-LABEL: Test128Acos: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll acosf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Acos: @@ -1840,17 +2226,20 @@ define fp128 @Test128Acos(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _acosl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1879,23 +2268,28 @@ define fp128 @Test128Asin(fp128 %a) nounwind { ; ; X86-LABEL: Test128Asin: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll asinf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Asin: @@ -1915,17 +2309,20 @@ define fp128 @Test128Asin(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _asinl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -1954,23 +2351,28 @@ define fp128 @Test128Atan(fp128 %a) nounwind { ; ; X86-LABEL: Test128Atan: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll atanf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Atan: @@ -1990,17 +2392,20 @@ define fp128 @Test128Atan(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _atanl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2029,27 +2434,40 @@ define fp128 @Test128Atan2(fp128 %a, fp128 %b) nounwind { ; ; X86-LABEL: Test128Atan2: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $76, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebp, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll atan2f128 -; X86-NEXT: addl $44, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $76, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Atan2: @@ -2069,24 +2487,32 @@ define fp128 @Test128Atan2(fp128 %a, fp128 %b) nounwind { ; WIN-X86: # %bb.0: ; WIN-X86-NEXT: pushl %ebp ; WIN-X86-NEXT: movl %esp, %ebp +; WIN-X86-NEXT: pushl %ebx ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $80, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 40(%ebp) -; WIN-X86-NEXT: pushl 36(%ebp) -; WIN-X86-NEXT: pushl 32(%ebp) -; WIN-X86-NEXT: pushl 28(%ebp) -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl 40(%ebp), %ebx +; WIN-X86-NEXT: movl 44(%ebp), %edx +; WIN-X86-NEXT: movl 48(%ebp), %ecx +; WIN-X86-NEXT: movl 52(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 32(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 28(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _atan2l -; WIN-X86-NEXT: addl $36, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2095,9 +2521,10 @@ define fp128 @Test128Atan2(fp128 %a, fp128 %b) nounwind { ; WIN-X86-NEXT: movl %ecx, 4(%esi) ; WIN-X86-NEXT: movl %eax, (%esi) ; WIN-X86-NEXT: movl %esi, %eax -; WIN-X86-NEXT: leal -8(%ebp), %esp +; WIN-X86-NEXT: leal -12(%ebp), %esp ; WIN-X86-NEXT: popl %esi ; WIN-X86-NEXT: popl %edi +; WIN-X86-NEXT: popl %ebx ; WIN-X86-NEXT: popl %ebp ; WIN-X86-NEXT: retl %x = call fp128 @llvm.atan2.f128(fp128 %a, fp128 %b) @@ -2115,23 +2542,28 @@ define fp128 @Test128Cosh(fp128 %a) nounwind { ; ; X86-LABEL: Test128Cosh: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll coshf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Cosh: @@ -2151,17 +2583,20 @@ define fp128 @Test128Cosh(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _coshl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2190,23 +2625,28 @@ define fp128 @Test128Sinh(fp128 %a) nounwind { ; ; X86-LABEL: Test128Sinh: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll sinhf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Sinh: @@ -2226,17 +2666,20 @@ define fp128 @Test128Sinh(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _sinhl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2265,23 +2708,28 @@ define fp128 @Test128Tan(fp128 %a) nounwind { ; ; X86-LABEL: Test128Tan: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll tanf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Tan: @@ -2301,17 +2749,20 @@ define fp128 @Test128Tan(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _tanl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2340,23 +2791,28 @@ define fp128 @Test128Tanh(fp128 %a) nounwind { ; ; X86-LABEL: Test128Tanh: ; X86: # %bb.0: +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $24, %esp +; X86-NEXT: subl $52, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll tanhf128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $52, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Tanh: @@ -2376,17 +2832,20 @@ define fp128 @Test128Tanh(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $16, %esp +; WIN-X86-NEXT: subl $48, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi -; WIN-X86-NEXT: movl %esp, %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %eax +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _tanhl -; WIN-X86-NEXT: addl $20, %esp -; WIN-X86-NEXT: movl (%esp), %eax +; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %edi @@ -2425,27 +2884,34 @@ define { fp128, fp128 } @Test128Modf(fp128 %a) nounwind { ; ; X86-LABEL: Test128Modf: ; X86: # %bb.0: +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: subl $40, %esp +; X86-NEXT: subl $80, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: subl $8, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: leal {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl {{[0-9]+}}(%esp) -; X86-NEXT: pushl %ecx +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: calll modff128 -; X86-NEXT: addl $28, %esp -; X86-NEXT: movaps (%esp), %xmm0 +; X86-NEXT: subl $4, %esp +; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm0 ; X86-NEXT: movaps {{[0-9]+}}(%esp), %xmm1 ; X86-NEXT: movaps %xmm1, 16(%esi) ; X86-NEXT: movaps %xmm0, (%esi) ; X86-NEXT: movl %esi, %eax -; X86-NEXT: addl $40, %esp +; X86-NEXT: addl $80, %esp ; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx ; X86-NEXT: retl $4 ; ; WIN-LABEL: Test128Modf: @@ -2468,18 +2934,21 @@ define { fp128, fp128 } @Test128Modf(fp128 %a) nounwind { ; WIN-X86-NEXT: pushl %edi ; WIN-X86-NEXT: pushl %esi ; WIN-X86-NEXT: andl $-16, %esp -; WIN-X86-NEXT: subl $64, %esp +; WIN-X86-NEXT: subl $112, %esp ; WIN-X86-NEXT: movl 8(%ebp), %esi +; WIN-X86-NEXT: movl 24(%ebp), %eax +; WIN-X86-NEXT: movl 28(%ebp), %ecx +; WIN-X86-NEXT: movl 32(%ebp), %edx +; WIN-X86-NEXT: movl 36(%ebp), %edi +; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ebx +; WIN-X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; WIN-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; WIN-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx -; WIN-X86-NEXT: pushl %eax -; WIN-X86-NEXT: pushl 24(%ebp) -; WIN-X86-NEXT: pushl 20(%ebp) -; WIN-X86-NEXT: pushl 16(%ebp) -; WIN-X86-NEXT: pushl 12(%ebp) -; WIN-X86-NEXT: pushl %ecx +; WIN-X86-NEXT: movl %eax, (%esp) ; WIN-X86-NEXT: calll _modfl -; WIN-X86-NEXT: addl $24, %esp ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; WIN-X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; WIN-X86-NEXT: movl {{[0-9]+}}(%esp), %eax diff --git a/llvm/test/CodeGen/X86/freeze-vector.ll b/llvm/test/CodeGen/X86/freeze-vector.ll index 0f66d42697d97..953a5e7285fe4 100644 --- a/llvm/test/CodeGen/X86/freeze-vector.ll +++ b/llvm/test/CodeGen/X86/freeze-vector.ll @@ -171,15 +171,15 @@ define void @freeze_extractelement(ptr %origin0, ptr %origin1, ptr %dst) nounwin ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: vmovdqa (%ecx), %xmm0 -; X86-NEXT: vpand (%edx), %xmm0, %xmm0 +; X86-NEXT: vmovdqa (%edx), %xmm0 +; X86-NEXT: vpand (%ecx), %xmm0, %xmm0 ; X86-NEXT: vpextrb $6, %xmm0, (%eax) ; X86-NEXT: retl ; ; X64-LABEL: freeze_extractelement: ; X64: # %bb.0: -; X64-NEXT: vmovdqa (%rsi), %xmm0 -; X64-NEXT: vpand (%rdi), %xmm0, %xmm0 +; X64-NEXT: vmovdqa (%rdi), %xmm0 +; X64-NEXT: vpand (%rsi), %xmm0, %xmm0 ; X64-NEXT: vpextrb $6, %xmm0, (%rdx) ; X64-NEXT: retq %i0 = load <16 x i8>, ptr %origin0 @@ -198,8 +198,8 @@ define void @freeze_extractelement_escape(ptr %origin0, ptr %origin1, ptr %dst, ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: vmovdqa (%edx), %xmm0 -; X86-NEXT: vpand (%esi), %xmm0, %xmm0 +; X86-NEXT: vmovdqa (%esi), %xmm0 +; X86-NEXT: vpand (%edx), %xmm0, %xmm0 ; X86-NEXT: vmovdqa %xmm0, (%ecx) ; X86-NEXT: vpextrb $6, %xmm0, (%eax) ; X86-NEXT: popl %esi @@ -207,8 +207,8 @@ define void @freeze_extractelement_escape(ptr %origin0, ptr %origin1, ptr %dst, ; ; X64-LABEL: freeze_extractelement_escape: ; X64: # %bb.0: -; X64-NEXT: vmovdqa (%rsi), %xmm0 -; X64-NEXT: vpand (%rdi), %xmm0, %xmm0 +; X64-NEXT: vmovdqa (%rdi), %xmm0 +; X64-NEXT: vpand (%rsi), %xmm0, %xmm0 ; X64-NEXT: vmovdqa %xmm0, (%rcx) ; X64-NEXT: vpextrb $6, %xmm0, (%rdx) ; X64-NEXT: retq @@ -239,8 +239,8 @@ define void @freeze_extractelement_extra_use(ptr %origin0, ptr %origin1, i64 %id ; X86-NEXT: movl 32(%ebp), %edx ; X86-NEXT: movl 12(%ebp), %esi ; X86-NEXT: movl 8(%ebp), %edi -; X86-NEXT: vmovaps (%esi), %xmm0 -; X86-NEXT: vandps (%edi), %xmm0, %xmm0 +; X86-NEXT: vmovaps (%edi), %xmm0 +; X86-NEXT: vandps (%esi), %xmm0, %xmm0 ; X86-NEXT: vmovaps %xmm0, (%esp) ; X86-NEXT: movzbl (%esp,%ecx), %ecx ; X86-NEXT: cmpb (%esp,%eax), %cl @@ -255,8 +255,8 @@ define void @freeze_extractelement_extra_use(ptr %origin0, ptr %origin1, i64 %id ; X64: # %bb.0: ; X64-NEXT: andl $15, %ecx ; X64-NEXT: andl $15, %edx -; X64-NEXT: vmovaps (%rsi), %xmm0 -; X64-NEXT: vandps (%rdi), %xmm0, %xmm0 +; X64-NEXT: vmovaps (%rdi), %xmm0 +; X64-NEXT: vandps (%rsi), %xmm0, %xmm0 ; X64-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; X64-NEXT: movzbl -24(%rsp,%rdx), %eax ; X64-NEXT: cmpb -24(%rsp,%rcx), %al diff --git a/llvm/test/CodeGen/X86/fshl.ll b/llvm/test/CodeGen/X86/fshl.ll index e8c8ccfa8d37f..ec1b8a3c8d6d9 100644 --- a/llvm/test/CodeGen/X86/fshl.ll +++ b/llvm/test/CodeGen/X86/fshl.ll @@ -264,53 +264,62 @@ define i128 @var_shift_i128(i128 %x, i128 %y, i128 %z) nounwind { ; X86-FAST-LABEL: var_shift_i128: ; X86-FAST: # %bb.0: ; X86-FAST-NEXT: pushl %ebp +; X86-FAST-NEXT: movl %esp, %ebp ; X86-FAST-NEXT: pushl %ebx ; X86-FAST-NEXT: pushl %edi ; X86-FAST-NEXT: pushl %esi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-FAST-NEXT: andl $-16, %esp +; X86-FAST-NEXT: subl $16, %esp +; X86-FAST-NEXT: movl 24(%ebp), %edi +; X86-FAST-NEXT: movl 28(%ebp), %edx +; X86-FAST-NEXT: movl 48(%ebp), %esi +; X86-FAST-NEXT: movl 56(%ebp), %ecx ; X86-FAST-NEXT: testb $64, %cl +; X86-FAST-NEXT: movl 52(%ebp), %eax ; X86-FAST-NEXT: jne .LBB6_1 ; X86-FAST-NEXT: # %bb.2: -; X86-FAST-NEXT: movl %ebx, %ebp ; X86-FAST-NEXT: movl %esi, %ebx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-FAST-NEXT: movl %edi, %eax -; X86-FAST-NEXT: movl %edx, %edi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-FAST-NEXT: movl %edi, %esi +; X86-FAST-NEXT: movl 32(%ebp), %edi +; X86-FAST-NEXT: movl %eax, (%esp) # 4-byte Spill +; X86-FAST-NEXT: movl %edx, %eax +; X86-FAST-NEXT: movl 36(%ebp), %edx ; X86-FAST-NEXT: testb $32, %cl ; X86-FAST-NEXT: je .LBB6_5 ; X86-FAST-NEXT: .LBB6_4: -; X86-FAST-NEXT: movl %esi, %edx -; X86-FAST-NEXT: movl %edi, %esi -; X86-FAST-NEXT: movl %ebx, %edi -; X86-FAST-NEXT: movl %eax, %ebx +; X86-FAST-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-FAST-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-FAST-NEXT: movl %esi, %eax +; X86-FAST-NEXT: movl (%esp), %esi # 4-byte Reload ; X86-FAST-NEXT: jmp .LBB6_6 ; X86-FAST-NEXT: .LBB6_1: -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-FAST-NEXT: movl 44(%ebp), %ebx +; X86-FAST-NEXT: movl %ebx, (%esp) # 4-byte Spill +; X86-FAST-NEXT: movl 40(%ebp), %ebx ; X86-FAST-NEXT: testb $32, %cl ; X86-FAST-NEXT: jne .LBB6_4 ; X86-FAST-NEXT: .LBB6_5: -; X86-FAST-NEXT: movl %eax, %ebp +; X86-FAST-NEXT: movl (%esp), %ebx # 4-byte Reload +; X86-FAST-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-FAST-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-FAST-NEXT: .LBB6_6: -; X86-FAST-NEXT: movl %ebx, %eax -; X86-FAST-NEXT: shldl %cl, %ebp, %eax -; X86-FAST-NEXT: movl %edi, %ebp -; X86-FAST-NEXT: shldl %cl, %ebx, %ebp -; X86-FAST-NEXT: movl %esi, %ebx -; X86-FAST-NEXT: shldl %cl, %edi, %ebx +; X86-FAST-NEXT: movl %esi, %edi +; X86-FAST-NEXT: shldl %cl, %ebx, %edi +; X86-FAST-NEXT: movl %eax, %edx +; X86-FAST-NEXT: movl %eax, %ebx +; X86-FAST-NEXT: shldl %cl, %esi, %ebx +; X86-FAST-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-FAST-NEXT: movl %eax, %esi +; X86-FAST-NEXT: shldl %cl, %edx, %esi ; X86-FAST-NEXT: # kill: def $cl killed $cl killed $ecx -; X86-FAST-NEXT: shldl %cl, %esi, %edx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-FAST-NEXT: movl %edx, 12(%ecx) -; X86-FAST-NEXT: movl %ebx, 8(%ecx) -; X86-FAST-NEXT: movl %ebp, 4(%ecx) -; X86-FAST-NEXT: movl %eax, (%ecx) -; X86-FAST-NEXT: movl %ecx, %eax +; X86-FAST-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload +; X86-FAST-NEXT: shldl %cl, %eax, %edx +; X86-FAST-NEXT: movl 8(%ebp), %eax +; X86-FAST-NEXT: movl %edx, 12(%eax) +; X86-FAST-NEXT: movl %esi, 8(%eax) +; X86-FAST-NEXT: movl %ebx, 4(%eax) +; X86-FAST-NEXT: movl %edi, (%eax) +; X86-FAST-NEXT: leal -12(%ebp), %esp ; X86-FAST-NEXT: popl %esi ; X86-FAST-NEXT: popl %edi ; X86-FAST-NEXT: popl %ebx @@ -320,77 +329,91 @@ define i128 @var_shift_i128(i128 %x, i128 %y, i128 %z) nounwind { ; X86-SLOW-LABEL: var_shift_i128: ; X86-SLOW: # %bb.0: ; X86-SLOW-NEXT: pushl %ebp +; X86-SLOW-NEXT: movl %esp, %ebp ; X86-SLOW-NEXT: pushl %ebx ; X86-SLOW-NEXT: pushl %edi ; X86-SLOW-NEXT: pushl %esi -; X86-SLOW-NEXT: pushl %eax -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-SLOW-NEXT: testb $64, %al +; X86-SLOW-NEXT: andl $-16, %esp +; X86-SLOW-NEXT: subl $32, %esp +; X86-SLOW-NEXT: movl 24(%ebp), %esi +; X86-SLOW-NEXT: movl 28(%ebp), %eax +; X86-SLOW-NEXT: movl 48(%ebp), %edx +; X86-SLOW-NEXT: movl 56(%ebp), %ecx +; X86-SLOW-NEXT: testb $64, %cl +; X86-SLOW-NEXT: movl 52(%ebp), %edi ; X86-SLOW-NEXT: jne .LBB6_1 ; X86-SLOW-NEXT: # %bb.2: -; X86-SLOW-NEXT: movl %edx, %ebp -; X86-SLOW-NEXT: movl %ebx, %edx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-SLOW-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %esi, %edx +; X86-SLOW-NEXT: movl 32(%ebp), %esi ; X86-SLOW-NEXT: movl %edi, %ecx -; X86-SLOW-NEXT: movl %esi, %edi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-SLOW-NEXT: testb $32, %al -; X86-SLOW-NEXT: je .LBB6_5 -; X86-SLOW-NEXT: .LBB6_4: -; X86-SLOW-NEXT: movl %ebx, (%esp) # 4-byte Spill -; X86-SLOW-NEXT: movl %edi, %ebx -; X86-SLOW-NEXT: movl %edx, %edi -; X86-SLOW-NEXT: movl %ecx, %edx -; X86-SLOW-NEXT: jmp .LBB6_6 +; X86-SLOW-NEXT: movl %eax, %edi +; X86-SLOW-NEXT: movl 36(%ebp), %eax +; X86-SLOW-NEXT: jmp .LBB6_3 ; X86-SLOW-NEXT: .LBB6_1: -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-SLOW-NEXT: testb $32, %al +; X86-SLOW-NEXT: movl 40(%ebp), %ecx +; X86-SLOW-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl 44(%ebp), %ecx +; X86-SLOW-NEXT: .LBB6_3: +; X86-SLOW-NEXT: movl 56(%ebp), %ebx +; X86-SLOW-NEXT: testb $32, %bl ; X86-SLOW-NEXT: jne .LBB6_4 -; X86-SLOW-NEXT: .LBB6_5: -; X86-SLOW-NEXT: movl %ecx, %ebp -; X86-SLOW-NEXT: movl %esi, (%esp) # 4-byte Spill +; X86-SLOW-NEXT: # %bb.5: +; X86-SLOW-NEXT: movl %ecx, %ebx +; X86-SLOW-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: jmp .LBB6_6 +; X86-SLOW-NEXT: .LBB6_4: +; X86-SLOW-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %ecx, %edx +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload ; X86-SLOW-NEXT: .LBB6_6: ; X86-SLOW-NEXT: movl %edx, %esi -; X86-SLOW-NEXT: movl %eax, %ecx -; X86-SLOW-NEXT: shll %cl, %esi -; X86-SLOW-NEXT: shrl %ebp -; X86-SLOW-NEXT: movb %al, %ch -; X86-SLOW-NEXT: notb %ch -; X86-SLOW-NEXT: movb %ch, %cl -; X86-SLOW-NEXT: shrl %cl, %ebp -; X86-SLOW-NEXT: orl %esi, %ebp -; X86-SLOW-NEXT: movl %edi, %esi -; X86-SLOW-NEXT: movb %al, %cl -; X86-SLOW-NEXT: shll %cl, %esi -; X86-SLOW-NEXT: shrl %edx -; X86-SLOW-NEXT: movb %ch, %cl -; X86-SLOW-NEXT: shrl %cl, %edx -; X86-SLOW-NEXT: orl %esi, %edx -; X86-SLOW-NEXT: movl %ebx, %esi -; X86-SLOW-NEXT: movb %al, %cl +; X86-SLOW-NEXT: movl 56(%ebp), %ecx ; X86-SLOW-NEXT: shll %cl, %esi +; X86-SLOW-NEXT: movl %ebx, %edi ; X86-SLOW-NEXT: shrl %edi -; X86-SLOW-NEXT: movb %ch, %cl +; X86-SLOW-NEXT: movl %ecx, %ebx +; X86-SLOW-NEXT: notb %bl +; X86-SLOW-NEXT: movl %ebx, %ecx +; X86-SLOW-NEXT: movb %bl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ; X86-SLOW-NEXT: shrl %cl, %edi ; X86-SLOW-NEXT: orl %esi, %edi -; X86-SLOW-NEXT: movb %al, %cl -; X86-SLOW-NEXT: movl (%esp), %eax # 4-byte Reload +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload +; X86-SLOW-NEXT: movl %esi, %eax +; X86-SLOW-NEXT: movl 56(%ebp), %ecx +; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-SLOW-NEXT: shll %cl, %eax +; X86-SLOW-NEXT: shrl %edx +; X86-SLOW-NEXT: movl %ebx, %ecx +; X86-SLOW-NEXT: shrl %cl, %edx +; X86-SLOW-NEXT: orl %eax, %edx +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload +; X86-SLOW-NEXT: movl %ebx, %eax +; X86-SLOW-NEXT: movl 56(%ebp), %ecx +; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-SLOW-NEXT: shll %cl, %eax +; X86-SLOW-NEXT: shrl %esi +; X86-SLOW-NEXT: movzbl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 1-byte Folded Reload +; X86-SLOW-NEXT: shrl %cl, %esi +; X86-SLOW-NEXT: orl %eax, %esi +; X86-SLOW-NEXT: movl 56(%ebp), %ecx +; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload ; X86-SLOW-NEXT: shll %cl, %eax ; X86-SLOW-NEXT: shrl %ebx -; X86-SLOW-NEXT: movb %ch, %cl +; X86-SLOW-NEXT: movzbl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 1-byte Folded Reload ; X86-SLOW-NEXT: shrl %cl, %ebx ; X86-SLOW-NEXT: orl %eax, %ebx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SLOW-NEXT: movl 8(%ebp), %eax ; X86-SLOW-NEXT: movl %ebx, 12(%eax) -; X86-SLOW-NEXT: movl %edi, 8(%eax) +; X86-SLOW-NEXT: movl %esi, 8(%eax) ; X86-SLOW-NEXT: movl %edx, 4(%eax) -; X86-SLOW-NEXT: movl %ebp, (%eax) -; X86-SLOW-NEXT: addl $4, %esp +; X86-SLOW-NEXT: movl %edi, (%eax) +; X86-SLOW-NEXT: leal -12(%ebp), %esp ; X86-SLOW-NEXT: popl %esi ; X86-SLOW-NEXT: popl %edi ; X86-SLOW-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/fshr.ll b/llvm/test/CodeGen/X86/fshr.ll index 4340f8fd484ae..544ab7fc77374 100644 --- a/llvm/test/CodeGen/X86/fshr.ll +++ b/llvm/test/CodeGen/X86/fshr.ll @@ -258,51 +258,53 @@ define i128 @var_shift_i128(i128 %x, i128 %y, i128 %z) nounwind { ; X86-FAST-LABEL: var_shift_i128: ; X86-FAST: # %bb.0: ; X86-FAST-NEXT: pushl %ebp +; X86-FAST-NEXT: movl %esp, %ebp ; X86-FAST-NEXT: pushl %ebx ; X86-FAST-NEXT: pushl %edi ; X86-FAST-NEXT: pushl %esi -; X86-FAST-NEXT: pushl %eax -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-FAST-NEXT: andl $-16, %esp +; X86-FAST-NEXT: subl $16, %esp +; X86-FAST-NEXT: movl 24(%ebp), %esi +; X86-FAST-NEXT: movl 28(%ebp), %eax +; X86-FAST-NEXT: movl 48(%ebp), %edx +; X86-FAST-NEXT: movl 56(%ebp), %ecx ; X86-FAST-NEXT: testb $64, %cl +; X86-FAST-NEXT: movl 52(%ebp), %ebx ; X86-FAST-NEXT: je .LBB6_1 ; X86-FAST-NEXT: # %bb.2: -; X86-FAST-NEXT: movl %edx, (%esp) # 4-byte Spill -; X86-FAST-NEXT: movl %edi, %edx -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-FAST-NEXT: movl %esi, %ebp -; X86-FAST-NEXT: movl %ebx, %esi -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X86-FAST-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-FAST-NEXT: movl %esi, %edx +; X86-FAST-NEXT: movl 32(%ebp), %esi +; X86-FAST-NEXT: movl %ebx, %edi +; X86-FAST-NEXT: movl %eax, %ebx +; X86-FAST-NEXT: movl 36(%ebp), %eax ; X86-FAST-NEXT: testb $32, %cl ; X86-FAST-NEXT: je .LBB6_4 ; X86-FAST-NEXT: jmp .LBB6_5 ; X86-FAST-NEXT: .LBB6_1: -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-FAST-NEXT: movl %ebp, (%esp) # 4-byte Spill -; X86-FAST-NEXT: movl {{[0-9]+}}(%esp), %ebp +; X86-FAST-NEXT: movl 40(%ebp), %edi +; X86-FAST-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-FAST-NEXT: movl 44(%ebp), %edi ; X86-FAST-NEXT: testb $32, %cl ; X86-FAST-NEXT: jne .LBB6_5 ; X86-FAST-NEXT: .LBB6_4: -; X86-FAST-NEXT: movl %edi, %ebx -; X86-FAST-NEXT: movl %esi, %edi -; X86-FAST-NEXT: movl %edx, %esi -; X86-FAST-NEXT: movl %ebp, %edx -; X86-FAST-NEXT: movl (%esp), %ebp # 4-byte Reload +; X86-FAST-NEXT: movl %esi, %eax +; X86-FAST-NEXT: movl %ebx, %esi +; X86-FAST-NEXT: movl %edx, %ebx +; X86-FAST-NEXT: movl %edi, %edx +; X86-FAST-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload ; X86-FAST-NEXT: .LBB6_5: -; X86-FAST-NEXT: shrdl %cl, %edx, %ebp -; X86-FAST-NEXT: shrdl %cl, %esi, %edx -; X86-FAST-NEXT: shrdl %cl, %edi, %esi +; X86-FAST-NEXT: shrdl %cl, %edx, %edi +; X86-FAST-NEXT: shrdl %cl, %ebx, %edx +; X86-FAST-NEXT: shrdl %cl, %esi, %ebx ; X86-FAST-NEXT: # kill: def $cl killed $cl killed $ecx -; X86-FAST-NEXT: shrdl %cl, %ebx, %edi -; X86-FAST-NEXT: movl %edi, 12(%eax) -; X86-FAST-NEXT: movl %esi, 8(%eax) +; X86-FAST-NEXT: shrdl %cl, %eax, %esi +; X86-FAST-NEXT: movl 8(%ebp), %eax +; X86-FAST-NEXT: movl %esi, 12(%eax) +; X86-FAST-NEXT: movl %ebx, 8(%eax) ; X86-FAST-NEXT: movl %edx, 4(%eax) -; X86-FAST-NEXT: movl %ebp, (%eax) -; X86-FAST-NEXT: addl $4, %esp +; X86-FAST-NEXT: movl %edi, (%eax) +; X86-FAST-NEXT: leal -12(%ebp), %esp ; X86-FAST-NEXT: popl %esi ; X86-FAST-NEXT: popl %edi ; X86-FAST-NEXT: popl %ebx @@ -312,78 +314,88 @@ define i128 @var_shift_i128(i128 %x, i128 %y, i128 %z) nounwind { ; X86-SLOW-LABEL: var_shift_i128: ; X86-SLOW: # %bb.0: ; X86-SLOW-NEXT: pushl %ebp +; X86-SLOW-NEXT: movl %esp, %ebp ; X86-SLOW-NEXT: pushl %ebx ; X86-SLOW-NEXT: pushl %edi ; X86-SLOW-NEXT: pushl %esi -; X86-SLOW-NEXT: subl $8, %esp -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-SLOW-NEXT: testb $64, %cl +; X86-SLOW-NEXT: andl $-16, %esp +; X86-SLOW-NEXT: subl $16, %esp +; X86-SLOW-NEXT: movl 24(%ebp), %edx +; X86-SLOW-NEXT: movl 28(%ebp), %esi +; X86-SLOW-NEXT: movl 48(%ebp), %ebx +; X86-SLOW-NEXT: movl 56(%ebp), %eax +; X86-SLOW-NEXT: testb $64, %al +; X86-SLOW-NEXT: movl 52(%ebp), %edi ; X86-SLOW-NEXT: je .LBB6_1 ; X86-SLOW-NEXT: # %bb.2: -; X86-SLOW-NEXT: movl %ebp, %eax -; X86-SLOW-NEXT: movl %ebx, %ebp -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-SLOW-NEXT: movl %edi, %edx +; X86-SLOW-NEXT: movl %ebx, (%esp) # 4-byte Spill +; X86-SLOW-NEXT: movl %edx, %ebx +; X86-SLOW-NEXT: movl 32(%ebp), %edx +; X86-SLOW-NEXT: movl %edi, %eax ; X86-SLOW-NEXT: movl %esi, %edi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-SLOW-NEXT: testb $32, %cl -; X86-SLOW-NEXT: jne .LBB6_5 -; X86-SLOW-NEXT: .LBB6_4: -; X86-SLOW-NEXT: movl %ebx, %esi -; X86-SLOW-NEXT: movl %edi, (%esp) # 4-byte Spill -; X86-SLOW-NEXT: movl %ebp, %edi -; X86-SLOW-NEXT: movl %edx, %ebp -; X86-SLOW-NEXT: movl %eax, %edx -; X86-SLOW-NEXT: jmp .LBB6_6 +; X86-SLOW-NEXT: movl 36(%ebp), %esi +; X86-SLOW-NEXT: jmp .LBB6_3 ; X86-SLOW-NEXT: .LBB6_1: -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-SLOW-NEXT: movl 40(%ebp), %eax +; X86-SLOW-NEXT: movl %eax, (%esp) # 4-byte Spill +; X86-SLOW-NEXT: movl 44(%ebp), %eax +; X86-SLOW-NEXT: .LBB6_3: +; X86-SLOW-NEXT: movl 56(%ebp), %ecx ; X86-SLOW-NEXT: testb $32, %cl ; X86-SLOW-NEXT: je .LBB6_4 -; X86-SLOW-NEXT: .LBB6_5: -; X86-SLOW-NEXT: movl %ebx, (%esp) # 4-byte Spill +; X86-SLOW-NEXT: # %bb.5: +; X86-SLOW-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: jmp .LBB6_6 +; X86-SLOW-NEXT: .LBB6_4: +; X86-SLOW-NEXT: movl %edx, %esi +; X86-SLOW-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl %eax, %ebx +; X86-SLOW-NEXT: movl (%esp), %eax # 4-byte Reload ; X86-SLOW-NEXT: .LBB6_6: -; X86-SLOW-NEXT: shrl %cl, %edx -; X86-SLOW-NEXT: movl %ecx, %ebx -; X86-SLOW-NEXT: notb %bl -; X86-SLOW-NEXT: leal (%ebp,%ebp), %eax -; X86-SLOW-NEXT: movl %ebx, %ecx -; X86-SLOW-NEXT: shll %cl, %eax -; X86-SLOW-NEXT: orl %edx, %eax -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SLOW-NEXT: shrl %cl, %eax +; X86-SLOW-NEXT: movl %eax, %edx +; X86-SLOW-NEXT: movl %ecx, %eax +; X86-SLOW-NEXT: notb %al +; X86-SLOW-NEXT: movl %ebx, %edi +; X86-SLOW-NEXT: addl %ebx, %ebx +; X86-SLOW-NEXT: movl %eax, %ecx +; X86-SLOW-NEXT: shll %cl, %ebx +; X86-SLOW-NEXT: orl %edx, %ebx +; X86-SLOW-NEXT: movl %ebx, (%esp) # 4-byte Spill +; X86-SLOW-NEXT: movl 56(%ebp), %ecx ; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx -; X86-SLOW-NEXT: shrl %cl, %ebp -; X86-SLOW-NEXT: leal (%edi,%edi), %edx -; X86-SLOW-NEXT: movl %ebx, %ecx +; X86-SLOW-NEXT: shrl %cl, %edi +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Reload +; X86-SLOW-NEXT: leal (%ebx,%ebx), %edx +; X86-SLOW-NEXT: movl %eax, %ecx ; X86-SLOW-NEXT: shll %cl, %edx -; X86-SLOW-NEXT: orl %ebp, %edx -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SLOW-NEXT: orl %edi, %edx +; X86-SLOW-NEXT: movl 56(%ebp), %ecx ; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx -; X86-SLOW-NEXT: shrl %cl, %edi -; X86-SLOW-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-SLOW-NEXT: movl (%esp), %edi # 4-byte Reload -; X86-SLOW-NEXT: leal (%edi,%edi), %ebp -; X86-SLOW-NEXT: movl %ebx, %ecx -; X86-SLOW-NEXT: shll %cl, %ebp -; X86-SLOW-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %ebp # 4-byte Folded Reload -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SLOW-NEXT: shrl %cl, %ebx +; X86-SLOW-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SLOW-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload +; X86-SLOW-NEXT: leal (%edi,%edi), %ebx +; X86-SLOW-NEXT: movl %eax, %ecx +; X86-SLOW-NEXT: shll %cl, %ebx +; X86-SLOW-NEXT: orl {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload +; X86-SLOW-NEXT: movl 56(%ebp), %ecx ; X86-SLOW-NEXT: # kill: def $cl killed $cl killed $ecx ; X86-SLOW-NEXT: shrl %cl, %edi ; X86-SLOW-NEXT: addl %esi, %esi -; X86-SLOW-NEXT: movl %ebx, %ecx +; X86-SLOW-NEXT: movl %eax, %ecx ; X86-SLOW-NEXT: shll %cl, %esi ; X86-SLOW-NEXT: orl %edi, %esi -; X86-SLOW-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SLOW-NEXT: movl 8(%ebp), %ecx ; X86-SLOW-NEXT: movl %esi, 12(%ecx) -; X86-SLOW-NEXT: movl %ebp, 8(%ecx) +; X86-SLOW-NEXT: movl %ebx, 8(%ecx) ; X86-SLOW-NEXT: movl %edx, 4(%ecx) +; X86-SLOW-NEXT: movl (%esp), %eax # 4-byte Reload ; X86-SLOW-NEXT: movl %eax, (%ecx) ; X86-SLOW-NEXT: movl %ecx, %eax -; X86-SLOW-NEXT: addl $8, %esp +; X86-SLOW-NEXT: leal -12(%ebp), %esp ; X86-SLOW-NEXT: popl %esi ; X86-SLOW-NEXT: popl %edi ; X86-SLOW-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/funnel-shift.ll b/llvm/test/CodeGen/X86/funnel-shift.ll index a464d78f9af38..df97f49440f74 100644 --- a/llvm/test/CodeGen/X86/funnel-shift.ll +++ b/llvm/test/CodeGen/X86/funnel-shift.ll @@ -74,43 +74,57 @@ define i128 @fshl_i128(i128 %x, i128 %y, i128 %z) nounwind { ; X86-SSE2-LABEL: fshl_i128: ; X86-SSE2: # %bb.0: ; X86-SSE2-NEXT: pushl %ebp +; X86-SSE2-NEXT: movl %esp, %ebp ; X86-SSE2-NEXT: pushl %ebx ; X86-SSE2-NEXT: pushl %edi ; X86-SSE2-NEXT: pushl %esi -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: andl $-16, %esp +; X86-SSE2-NEXT: subl $16, %esp +; X86-SSE2-NEXT: movl 48(%ebp), %edi +; X86-SSE2-NEXT: movl 52(%ebp), %eax +; X86-SSE2-NEXT: movl 24(%ebp), %edx +; X86-SSE2-NEXT: movl 56(%ebp), %ecx ; X86-SSE2-NEXT: testb $64, %cl -; X86-SSE2-NEXT: movl %esi, %eax -; X86-SSE2-NEXT: cmovnel %ebx, %eax -; X86-SSE2-NEXT: movl %edx, %ebp -; X86-SSE2-NEXT: cmovnel %edi, %ebp -; X86-SSE2-NEXT: cmovnel {{[0-9]+}}(%esp), %edi -; X86-SSE2-NEXT: cmovnel {{[0-9]+}}(%esp), %ebx -; X86-SSE2-NEXT: cmovel {{[0-9]+}}(%esp), %edx -; X86-SSE2-NEXT: cmovel {{[0-9]+}}(%esp), %esi +; X86-SSE2-NEXT: movl %edx, %ecx +; X86-SSE2-NEXT: cmovnel %edi, %ecx +; X86-SSE2-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SSE2-NEXT: movl 28(%ebp), %esi +; X86-SSE2-NEXT: movl %esi, %ebx +; X86-SSE2-NEXT: cmovnel %eax, %ebx +; X86-SSE2-NEXT: cmovnel 44(%ebp), %eax +; X86-SSE2-NEXT: cmovnel 40(%ebp), %edi +; X86-SSE2-NEXT: cmovel 36(%ebp), %esi +; X86-SSE2-NEXT: cmovel 32(%ebp), %edx +; X86-SSE2-NEXT: movl 56(%ebp), %ecx ; X86-SSE2-NEXT: testb $32, %cl -; X86-SSE2-NEXT: cmovnel %esi, %edx -; X86-SSE2-NEXT: cmovnel %ebp, %esi -; X86-SSE2-NEXT: cmovnel %eax, %ebp -; X86-SSE2-NEXT: cmovel %edi, %ebx +; X86-SSE2-NEXT: cmovnel %edx, %esi +; X86-SSE2-NEXT: cmovnel %ebx, %edx +; X86-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-SSE2-NEXT: cmovnel %ecx, %ebx ; X86-SSE2-NEXT: cmovel %eax, %edi -; X86-SSE2-NEXT: movl %edi, %eax -; X86-SSE2-NEXT: shldl %cl, %ebx, %eax -; X86-SSE2-NEXT: movl %ebp, %ebx -; X86-SSE2-NEXT: shldl %cl, %edi, %ebx -; X86-SSE2-NEXT: movl %esi, %edi -; X86-SSE2-NEXT: shldl %cl, %ebp, %edi +; X86-SSE2-NEXT: cmovel %ecx, %eax +; X86-SSE2-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SSE2-NEXT: movl 56(%ebp), %ecx ; X86-SSE2-NEXT: # kill: def $cl killed $cl killed $ecx -; X86-SSE2-NEXT: shldl %cl, %esi, %edx -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-SSE2-NEXT: movl %edx, 12(%ecx) -; X86-SSE2-NEXT: movl %edi, 8(%ecx) -; X86-SSE2-NEXT: movl %ebx, 4(%ecx) -; X86-SSE2-NEXT: movl %eax, (%ecx) -; X86-SSE2-NEXT: movl %ecx, %eax +; X86-SSE2-NEXT: shldl %cl, %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Spill +; X86-SSE2-NEXT: movl %ebx, %edi +; X86-SSE2-NEXT: movl 56(%ebp), %ecx +; X86-SSE2-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-SSE2-NEXT: shldl %cl, %eax, %edi +; X86-SSE2-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-SSE2-NEXT: movl %edx, %edi +; X86-SSE2-NEXT: movl 56(%ebp), %ecx +; X86-SSE2-NEXT: shldl %cl, %ebx, %edi +; X86-SSE2-NEXT: movl 8(%ebp), %eax +; X86-SSE2-NEXT: # kill: def $cl killed $cl killed $ecx +; X86-SSE2-NEXT: shldl %cl, %edx, %esi +; X86-SSE2-NEXT: movl %esi, 12(%eax) +; X86-SSE2-NEXT: movl %edi, 8(%eax) +; X86-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-SSE2-NEXT: movl %ecx, 4(%eax) +; X86-SSE2-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-SSE2-NEXT: movl %ecx, (%eax) +; X86-SSE2-NEXT: leal -12(%ebp), %esp ; X86-SSE2-NEXT: popl %esi ; X86-SSE2-NEXT: popl %edi ; X86-SSE2-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/i128-add.ll b/llvm/test/CodeGen/X86/i128-add.ll index 2849e448a0534..b4546c1e983c4 100644 --- a/llvm/test/CodeGen/X86/i128-add.ll +++ b/llvm/test/CodeGen/X86/i128-add.ll @@ -5,17 +5,20 @@ define i128 @add_i128(i128 %x, i128 %y) nounwind { ; X86-LABEL: add_i128: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: addl {{[0-9]+}}(%esp), %esi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %edi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: adcl {{[0-9]+}}(%esp), %edx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %esi +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: addl 40(%ebp), %esi +; X86-NEXT: adcl 44(%ebp), %edi +; X86-NEXT: adcl 48(%ebp), %ecx +; X86-NEXT: adcl 52(%ebp), %edx ; X86-NEXT: addl $1, %esi ; X86-NEXT: adcl $0, %edi ; X86-NEXT: adcl $0, %ecx @@ -24,8 +27,10 @@ define i128 @add_i128(i128 %x, i128 %y) nounwind { ; X86-NEXT: movl %esi, (%eax) ; X86-NEXT: movl %ecx, 8(%eax) ; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: add_i128: diff --git a/llvm/test/CodeGen/X86/i128-fp128-abi.ll b/llvm/test/CodeGen/X86/i128-fp128-abi.ll index 4152dcf07f7e7..2174d5056e6ce 100644 --- a/llvm/test/CodeGen/X86/i128-fp128-abi.ll +++ b/llvm/test/CodeGen/X86/i128-fp128-abi.ll @@ -55,41 +55,47 @@ define void @store(PrimTy %x, ptr %p) nounwind { ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 12(%esp), %eax -; CHECK-X86-NEXT: movl 16(%esp), %ecx -; CHECK-X86-NEXT: movl 20(%esp), %edx -; CHECK-X86-NEXT: movl 24(%esp), %esi -; CHECK-X86-NEXT: movl 28(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 16(%esp), %eax +; CHECK-X86-NEXT: movl 20(%esp), %ecx +; CHECK-X86-NEXT: movl 24(%esp), %edx +; CHECK-X86-NEXT: movl 28(%esp), %esi +; CHECK-X86-NEXT: movl 32(%esp), %edi ; CHECK-X86-NEXT: movl %esi, 12(%edi) ; CHECK-X86-NEXT: movl %edx, 8(%edi) ; CHECK-X86-NEXT: movl %ecx, 4(%edi) ; CHECK-X86-NEXT: movl %eax, (%edi) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: store: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 12(%esp), %eax -; CHECK-MSVC32-NEXT: movl 16(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 20(%esp), %edx -; CHECK-MSVC32-NEXT: movl 24(%esp), %esi -; CHECK-MSVC32-NEXT: movl 28(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 12(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 16(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 20(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 24(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %esi, 12(%edi) ; CHECK-MSVC32-NEXT: movl %edx, 8(%edi) ; CHECK-MSVC32-NEXT: movl %ecx, 4(%edi) ; CHECK-MSVC32-NEXT: movl %eax, (%edi) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl store PrimTy %x, ptr %p ret void } ; Illustrate stack alignment -; FIXME(#77401): alignment on x86-32 is ABI-incorrect. define void @store_perturbed(i8 %_0, PrimTy %x, ptr %p) nounwind { ; CHECK-X64-F128-LABEL: store_perturbed: ; CHECK-X64-F128: # %bb.0: @@ -130,34 +136,41 @@ define void @store_perturbed(i8 %_0, PrimTy %x, ptr %p) nounwind { ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 16(%esp), %eax -; CHECK-X86-NEXT: movl 20(%esp), %ecx -; CHECK-X86-NEXT: movl 24(%esp), %edx -; CHECK-X86-NEXT: movl 28(%esp), %esi -; CHECK-X86-NEXT: movl 32(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 32(%esp), %eax +; CHECK-X86-NEXT: movl 36(%esp), %ecx +; CHECK-X86-NEXT: movl 40(%esp), %edx +; CHECK-X86-NEXT: movl 44(%esp), %esi +; CHECK-X86-NEXT: movl 48(%esp), %edi ; CHECK-X86-NEXT: movl %esi, 12(%edi) ; CHECK-X86-NEXT: movl %edx, 8(%edi) ; CHECK-X86-NEXT: movl %ecx, 4(%edi) ; CHECK-X86-NEXT: movl %eax, (%edi) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: store_perturbed: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 16(%esp), %eax -; CHECK-MSVC32-NEXT: movl 20(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 24(%esp), %edx -; CHECK-MSVC32-NEXT: movl 28(%esp), %esi -; CHECK-MSVC32-NEXT: movl 32(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 24(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 28(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 32(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 36(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 40(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %esi, 12(%edi) ; CHECK-MSVC32-NEXT: movl %edx, 8(%edi) ; CHECK-MSVC32-NEXT: movl %ecx, 4(%edi) ; CHECK-MSVC32-NEXT: movl %eax, (%edi) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl store PrimTy %x, ptr %p ret void @@ -271,34 +284,41 @@ define PrimTy @first_arg(PrimTy %x) nounwind { ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 12(%esp), %eax -; CHECK-X86-NEXT: movl 16(%esp), %ecx -; CHECK-X86-NEXT: movl 20(%esp), %edx -; CHECK-X86-NEXT: movl 24(%esp), %esi -; CHECK-X86-NEXT: movl 28(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 16(%esp), %eax +; CHECK-X86-NEXT: movl 32(%esp), %ecx +; CHECK-X86-NEXT: movl 36(%esp), %edx +; CHECK-X86-NEXT: movl 40(%esp), %esi +; CHECK-X86-NEXT: movl 44(%esp), %edi ; CHECK-X86-NEXT: movl %edi, 12(%eax) ; CHECK-X86-NEXT: movl %esi, 8(%eax) ; CHECK-X86-NEXT: movl %edx, 4(%eax) ; CHECK-X86-NEXT: movl %ecx, (%eax) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl $4 ; ; CHECK-MSVC32-LABEL: first_arg: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 12(%esp), %eax -; CHECK-MSVC32-NEXT: movl 16(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 20(%esp), %edx -; CHECK-MSVC32-NEXT: movl 24(%esp), %esi -; CHECK-MSVC32-NEXT: movl 28(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 24(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 28(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 32(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 36(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %edi, 12(%eax) ; CHECK-MSVC32-NEXT: movl %esi, 8(%eax) ; CHECK-MSVC32-NEXT: movl %edx, 4(%eax) ; CHECK-MSVC32-NEXT: movl %ecx, (%eax) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl ret PrimTy %x } @@ -344,34 +364,41 @@ define PrimTy @leading_args(i64 %_0, i64 %_1, i64 %_2, i64 %_3, PrimTy %x) nounw ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 12(%esp), %eax -; CHECK-X86-NEXT: movl 48(%esp), %ecx -; CHECK-X86-NEXT: movl 52(%esp), %edx -; CHECK-X86-NEXT: movl 56(%esp), %esi -; CHECK-X86-NEXT: movl 60(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 16(%esp), %eax +; CHECK-X86-NEXT: movl 64(%esp), %ecx +; CHECK-X86-NEXT: movl 68(%esp), %edx +; CHECK-X86-NEXT: movl 72(%esp), %esi +; CHECK-X86-NEXT: movl 76(%esp), %edi ; CHECK-X86-NEXT: movl %edi, 12(%eax) ; CHECK-X86-NEXT: movl %esi, 8(%eax) ; CHECK-X86-NEXT: movl %edx, 4(%eax) ; CHECK-X86-NEXT: movl %ecx, (%eax) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl $4 ; ; CHECK-MSVC32-LABEL: leading_args: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 12(%esp), %eax -; CHECK-MSVC32-NEXT: movl 48(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 52(%esp), %edx -; CHECK-MSVC32-NEXT: movl 56(%esp), %esi -; CHECK-MSVC32-NEXT: movl 60(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 56(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 60(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 64(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 68(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %edi, 12(%eax) ; CHECK-MSVC32-NEXT: movl %esi, 8(%eax) ; CHECK-MSVC32-NEXT: movl %edx, 4(%eax) ; CHECK-MSVC32-NEXT: movl %ecx, (%eax) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl ret PrimTy %x } @@ -417,34 +444,41 @@ define PrimTy @many_leading_args(i64 %_0, i64 %_1, i64 %_2, i64 %_3, i64 %_4, Pr ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 12(%esp), %eax -; CHECK-X86-NEXT: movl 72(%esp), %ecx -; CHECK-X86-NEXT: movl 76(%esp), %edx -; CHECK-X86-NEXT: movl 80(%esp), %esi -; CHECK-X86-NEXT: movl 84(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 16(%esp), %eax +; CHECK-X86-NEXT: movl 80(%esp), %ecx +; CHECK-X86-NEXT: movl 84(%esp), %edx +; CHECK-X86-NEXT: movl 88(%esp), %esi +; CHECK-X86-NEXT: movl 92(%esp), %edi ; CHECK-X86-NEXT: movl %edi, 12(%eax) ; CHECK-X86-NEXT: movl %esi, 8(%eax) ; CHECK-X86-NEXT: movl %edx, 4(%eax) ; CHECK-X86-NEXT: movl %ecx, (%eax) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl $4 ; ; CHECK-MSVC32-LABEL: many_leading_args: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 12(%esp), %eax -; CHECK-MSVC32-NEXT: movl 72(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 76(%esp), %edx -; CHECK-MSVC32-NEXT: movl 80(%esp), %esi -; CHECK-MSVC32-NEXT: movl 84(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 72(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 76(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 80(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 84(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %edi, 12(%eax) ; CHECK-MSVC32-NEXT: movl %esi, 8(%eax) ; CHECK-MSVC32-NEXT: movl %edx, 4(%eax) ; CHECK-MSVC32-NEXT: movl %ecx, (%eax) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl ret PrimTy %x } @@ -488,34 +522,41 @@ define PrimTy @trailing_arg(i64 %_0, i64 %_1, i64 %_2, i64 %_3, i64 %_4, PrimTy ; CHECK-X86: # %bb.0: ; CHECK-X86-NEXT: pushl %edi ; CHECK-X86-NEXT: pushl %esi -; CHECK-X86-NEXT: movl 12(%esp), %eax -; CHECK-X86-NEXT: movl 56(%esp), %ecx -; CHECK-X86-NEXT: movl 60(%esp), %edx -; CHECK-X86-NEXT: movl 64(%esp), %esi -; CHECK-X86-NEXT: movl 68(%esp), %edi +; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: movl 16(%esp), %eax +; CHECK-X86-NEXT: movl 64(%esp), %ecx +; CHECK-X86-NEXT: movl 68(%esp), %edx +; CHECK-X86-NEXT: movl 72(%esp), %esi +; CHECK-X86-NEXT: movl 76(%esp), %edi ; CHECK-X86-NEXT: movl %edi, 12(%eax) ; CHECK-X86-NEXT: movl %esi, 8(%eax) ; CHECK-X86-NEXT: movl %edx, 4(%eax) ; CHECK-X86-NEXT: movl %ecx, (%eax) +; CHECK-X86-NEXT: addl $4, %esp ; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: popl %edi ; CHECK-X86-NEXT: retl $4 ; ; CHECK-MSVC32-LABEL: trailing_arg: ; CHECK-MSVC32: # %bb.0: +; CHECK-MSVC32-NEXT: pushl %ebp +; CHECK-MSVC32-NEXT: movl %esp, %ebp ; CHECK-MSVC32-NEXT: pushl %edi ; CHECK-MSVC32-NEXT: pushl %esi -; CHECK-MSVC32-NEXT: movl 12(%esp), %eax -; CHECK-MSVC32-NEXT: movl 56(%esp), %ecx -; CHECK-MSVC32-NEXT: movl 60(%esp), %edx -; CHECK-MSVC32-NEXT: movl 64(%esp), %esi -; CHECK-MSVC32-NEXT: movl 68(%esp), %edi +; CHECK-MSVC32-NEXT: andl $-16, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 56(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 60(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 64(%ebp), %esi +; CHECK-MSVC32-NEXT: movl 68(%ebp), %edi ; CHECK-MSVC32-NEXT: movl %edi, 12(%eax) ; CHECK-MSVC32-NEXT: movl %esi, 8(%eax) ; CHECK-MSVC32-NEXT: movl %edx, 4(%eax) ; CHECK-MSVC32-NEXT: movl %ecx, (%eax) +; CHECK-MSVC32-NEXT: leal -8(%ebp), %esp ; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %edi +; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl ret PrimTy %x } @@ -571,32 +612,43 @@ define void @call_first_arg(PrimTy %x) nounwind { ; ; CHECK-X86-LABEL: call_first_arg: ; CHECK-X86: # %bb.0: -; CHECK-X86-NEXT: subl $40, %esp -; CHECK-X86-NEXT: leal 12(%esp), %eax -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: pushl %esi +; CHECK-X86-NEXT: subl $56, %esp +; CHECK-X86-NEXT: movl 64(%esp), %eax +; CHECK-X86-NEXT: movl 68(%esp), %ecx +; CHECK-X86-NEXT: movl 72(%esp), %edx +; CHECK-X86-NEXT: movl 76(%esp), %esi +; CHECK-X86-NEXT: movl %esi, 28(%esp) +; CHECK-X86-NEXT: movl %edx, 24(%esp) +; CHECK-X86-NEXT: movl %ecx, 20(%esp) +; CHECK-X86-NEXT: movl %eax, 16(%esp) +; CHECK-X86-NEXT: leal 32(%esp), %eax +; CHECK-X86-NEXT: movl %eax, (%esp) ; CHECK-X86-NEXT: calll first_arg@PLT -; CHECK-X86-NEXT: addl $56, %esp +; CHECK-X86-NEXT: addl $52, %esp +; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: call_first_arg: ; CHECK-MSVC32: # %bb.0: ; CHECK-MSVC32-NEXT: pushl %ebp ; CHECK-MSVC32-NEXT: movl %esp, %ebp +; CHECK-MSVC32-NEXT: pushl %esi ; CHECK-MSVC32-NEXT: andl $-16, %esp -; CHECK-MSVC32-NEXT: subl $32, %esp -; CHECK-MSVC32-NEXT: movl %esp, %eax -; CHECK-MSVC32-NEXT: pushl 20(%ebp) -; CHECK-MSVC32-NEXT: pushl 16(%ebp) -; CHECK-MSVC32-NEXT: pushl 12(%ebp) -; CHECK-MSVC32-NEXT: pushl 8(%ebp) -; CHECK-MSVC32-NEXT: pushl %eax +; CHECK-MSVC32-NEXT: subl $64, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 12(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 16(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 20(%ebp), %esi +; CHECK-MSVC32-NEXT: movl %esi, 28(%esp) +; CHECK-MSVC32-NEXT: movl %edx, 24(%esp) +; CHECK-MSVC32-NEXT: movl %ecx, 20(%esp) +; CHECK-MSVC32-NEXT: movl %eax, 16(%esp) +; CHECK-MSVC32-NEXT: leal 32(%esp), %eax +; CHECK-MSVC32-NEXT: movl %eax, (%esp) ; CHECK-MSVC32-NEXT: calll _first_arg -; CHECK-MSVC32-NEXT: addl $20, %esp -; CHECK-MSVC32-NEXT: movl %ebp, %esp +; CHECK-MSVC32-NEXT: leal -4(%ebp), %esp +; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl call PrimTy @first_arg(PrimTy %x) @@ -686,48 +738,59 @@ define void @call_leading_args(PrimTy %x) nounwind { ; ; CHECK-X86-LABEL: call_leading_args: ; CHECK-X86: # %bb.0: -; CHECK-X86-NEXT: subl $40, %esp -; CHECK-X86-NEXT: leal 12(%esp), %eax -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: pushl %esi +; CHECK-X86-NEXT: subl $88, %esp +; CHECK-X86-NEXT: movl 96(%esp), %eax +; CHECK-X86-NEXT: movl 100(%esp), %ecx +; CHECK-X86-NEXT: movl 104(%esp), %edx +; CHECK-X86-NEXT: movl 108(%esp), %esi +; CHECK-X86-NEXT: movl %esi, 60(%esp) +; CHECK-X86-NEXT: movl %edx, 56(%esp) +; CHECK-X86-NEXT: movl %ecx, 52(%esp) +; CHECK-X86-NEXT: movl %eax, 48(%esp) +; CHECK-X86-NEXT: leal 64(%esp), %eax +; CHECK-X86-NEXT: movl %eax, (%esp) +; CHECK-X86-NEXT: movl $0, 32(%esp) +; CHECK-X86-NEXT: movl $0, 28(%esp) +; CHECK-X86-NEXT: movl $0, 24(%esp) +; CHECK-X86-NEXT: movl $0, 20(%esp) +; CHECK-X86-NEXT: movl $0, 16(%esp) +; CHECK-X86-NEXT: movl $0, 12(%esp) +; CHECK-X86-NEXT: movl $0, 8(%esp) +; CHECK-X86-NEXT: movl $0, 4(%esp) ; CHECK-X86-NEXT: calll leading_args@PLT -; CHECK-X86-NEXT: addl $88, %esp +; CHECK-X86-NEXT: addl $84, %esp +; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: call_leading_args: ; CHECK-MSVC32: # %bb.0: ; CHECK-MSVC32-NEXT: pushl %ebp ; CHECK-MSVC32-NEXT: movl %esp, %ebp +; CHECK-MSVC32-NEXT: pushl %esi ; CHECK-MSVC32-NEXT: andl $-16, %esp -; CHECK-MSVC32-NEXT: subl $32, %esp -; CHECK-MSVC32-NEXT: movl %esp, %eax -; CHECK-MSVC32-NEXT: pushl 20(%ebp) -; CHECK-MSVC32-NEXT: pushl 16(%ebp) -; CHECK-MSVC32-NEXT: pushl 12(%ebp) -; CHECK-MSVC32-NEXT: pushl 8(%ebp) -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl %eax +; CHECK-MSVC32-NEXT: subl $96, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 12(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 16(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 20(%ebp), %esi +; CHECK-MSVC32-NEXT: movl %esi, 60(%esp) +; CHECK-MSVC32-NEXT: movl %edx, 56(%esp) +; CHECK-MSVC32-NEXT: movl %ecx, 52(%esp) +; CHECK-MSVC32-NEXT: movl %eax, 48(%esp) +; CHECK-MSVC32-NEXT: leal 64(%esp), %eax +; CHECK-MSVC32-NEXT: movl %eax, (%esp) +; CHECK-MSVC32-NEXT: movl $0, 32(%esp) +; CHECK-MSVC32-NEXT: movl $0, 28(%esp) +; CHECK-MSVC32-NEXT: movl $0, 24(%esp) +; CHECK-MSVC32-NEXT: movl $0, 20(%esp) +; CHECK-MSVC32-NEXT: movl $0, 16(%esp) +; CHECK-MSVC32-NEXT: movl $0, 12(%esp) +; CHECK-MSVC32-NEXT: movl $0, 8(%esp) +; CHECK-MSVC32-NEXT: movl $0, 4(%esp) ; CHECK-MSVC32-NEXT: calll _leading_args -; CHECK-MSVC32-NEXT: addl $52, %esp -; CHECK-MSVC32-NEXT: movl %ebp, %esp +; CHECK-MSVC32-NEXT: leal -4(%ebp), %esp +; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl call PrimTy @leading_args(i64 0, i64 0, i64 0, i64 0, PrimTy %x) @@ -836,56 +899,67 @@ define void @call_many_leading_args(PrimTy %x) nounwind { ; ; CHECK-X86-LABEL: call_many_leading_args: ; CHECK-X86: # %bb.0: -; CHECK-X86-NEXT: subl $40, %esp -; CHECK-X86-NEXT: leal 12(%esp), %eax -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: pushl %esi +; CHECK-X86-NEXT: subl $104, %esp +; CHECK-X86-NEXT: movl 112(%esp), %eax +; CHECK-X86-NEXT: movl 116(%esp), %ecx +; CHECK-X86-NEXT: movl 120(%esp), %edx +; CHECK-X86-NEXT: movl 124(%esp), %esi +; CHECK-X86-NEXT: movl %esi, 76(%esp) +; CHECK-X86-NEXT: movl %edx, 72(%esp) +; CHECK-X86-NEXT: movl %ecx, 68(%esp) +; CHECK-X86-NEXT: movl %eax, 64(%esp) +; CHECK-X86-NEXT: leal 80(%esp), %eax +; CHECK-X86-NEXT: movl %eax, (%esp) +; CHECK-X86-NEXT: movl $0, 60(%esp) +; CHECK-X86-NEXT: movl $0, 56(%esp) +; CHECK-X86-NEXT: movl $0, 52(%esp) +; CHECK-X86-NEXT: movl $0, 48(%esp) +; CHECK-X86-NEXT: movl $0, 32(%esp) +; CHECK-X86-NEXT: movl $0, 28(%esp) +; CHECK-X86-NEXT: movl $0, 24(%esp) +; CHECK-X86-NEXT: movl $0, 20(%esp) +; CHECK-X86-NEXT: movl $0, 16(%esp) +; CHECK-X86-NEXT: movl $0, 12(%esp) +; CHECK-X86-NEXT: movl $0, 8(%esp) +; CHECK-X86-NEXT: movl $0, 4(%esp) ; CHECK-X86-NEXT: calll many_leading_args@PLT -; CHECK-X86-NEXT: addl $104, %esp +; CHECK-X86-NEXT: addl $100, %esp +; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: call_many_leading_args: ; CHECK-MSVC32: # %bb.0: ; CHECK-MSVC32-NEXT: pushl %ebp ; CHECK-MSVC32-NEXT: movl %esp, %ebp +; CHECK-MSVC32-NEXT: pushl %esi ; CHECK-MSVC32-NEXT: andl $-16, %esp -; CHECK-MSVC32-NEXT: subl $32, %esp -; CHECK-MSVC32-NEXT: movl %esp, %eax -; CHECK-MSVC32-NEXT: pushl 20(%ebp) -; CHECK-MSVC32-NEXT: pushl 16(%ebp) -; CHECK-MSVC32-NEXT: pushl 12(%ebp) -; CHECK-MSVC32-NEXT: pushl 8(%ebp) -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl %eax +; CHECK-MSVC32-NEXT: subl $112, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 12(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 16(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 20(%ebp), %esi +; CHECK-MSVC32-NEXT: movl %esi, 76(%esp) +; CHECK-MSVC32-NEXT: movl %edx, 72(%esp) +; CHECK-MSVC32-NEXT: movl %ecx, 68(%esp) +; CHECK-MSVC32-NEXT: movl %eax, 64(%esp) +; CHECK-MSVC32-NEXT: leal 80(%esp), %eax +; CHECK-MSVC32-NEXT: movl %eax, (%esp) +; CHECK-MSVC32-NEXT: movl $0, 60(%esp) +; CHECK-MSVC32-NEXT: movl $0, 56(%esp) +; CHECK-MSVC32-NEXT: movl $0, 52(%esp) +; CHECK-MSVC32-NEXT: movl $0, 48(%esp) +; CHECK-MSVC32-NEXT: movl $0, 32(%esp) +; CHECK-MSVC32-NEXT: movl $0, 28(%esp) +; CHECK-MSVC32-NEXT: movl $0, 24(%esp) +; CHECK-MSVC32-NEXT: movl $0, 20(%esp) +; CHECK-MSVC32-NEXT: movl $0, 16(%esp) +; CHECK-MSVC32-NEXT: movl $0, 12(%esp) +; CHECK-MSVC32-NEXT: movl $0, 8(%esp) +; CHECK-MSVC32-NEXT: movl $0, 4(%esp) ; CHECK-MSVC32-NEXT: calll _many_leading_args -; CHECK-MSVC32-NEXT: addl $68, %esp -; CHECK-MSVC32-NEXT: movl %ebp, %esp +; CHECK-MSVC32-NEXT: leal -4(%ebp), %esp +; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl call PrimTy @many_leading_args(i64 0, i64 0, i64 0, i64 0, PrimTy Prim0, PrimTy %x) @@ -975,48 +1049,59 @@ define void @call_trailing_arg(PrimTy %x) nounwind { ; ; CHECK-X86-LABEL: call_trailing_arg: ; CHECK-X86: # %bb.0: -; CHECK-X86-NEXT: subl $40, %esp -; CHECK-X86-NEXT: leal 12(%esp), %eax -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl 56(%esp) -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl $0 -; CHECK-X86-NEXT: pushl %eax +; CHECK-X86-NEXT: pushl %esi +; CHECK-X86-NEXT: subl $88, %esp +; CHECK-X86-NEXT: movl 96(%esp), %eax +; CHECK-X86-NEXT: movl 100(%esp), %ecx +; CHECK-X86-NEXT: movl 104(%esp), %edx +; CHECK-X86-NEXT: movl 108(%esp), %esi +; CHECK-X86-NEXT: movl %esi, 60(%esp) +; CHECK-X86-NEXT: movl %edx, 56(%esp) +; CHECK-X86-NEXT: movl %ecx, 52(%esp) +; CHECK-X86-NEXT: movl %eax, 48(%esp) +; CHECK-X86-NEXT: leal 64(%esp), %eax +; CHECK-X86-NEXT: movl %eax, (%esp) +; CHECK-X86-NEXT: movl $0, 32(%esp) +; CHECK-X86-NEXT: movl $0, 28(%esp) +; CHECK-X86-NEXT: movl $0, 24(%esp) +; CHECK-X86-NEXT: movl $0, 20(%esp) +; CHECK-X86-NEXT: movl $0, 16(%esp) +; CHECK-X86-NEXT: movl $0, 12(%esp) +; CHECK-X86-NEXT: movl $0, 8(%esp) +; CHECK-X86-NEXT: movl $0, 4(%esp) ; CHECK-X86-NEXT: calll trailing_arg@PLT -; CHECK-X86-NEXT: addl $88, %esp +; CHECK-X86-NEXT: addl $84, %esp +; CHECK-X86-NEXT: popl %esi ; CHECK-X86-NEXT: retl ; ; CHECK-MSVC32-LABEL: call_trailing_arg: ; CHECK-MSVC32: # %bb.0: ; CHECK-MSVC32-NEXT: pushl %ebp ; CHECK-MSVC32-NEXT: movl %esp, %ebp +; CHECK-MSVC32-NEXT: pushl %esi ; CHECK-MSVC32-NEXT: andl $-16, %esp -; CHECK-MSVC32-NEXT: subl $32, %esp -; CHECK-MSVC32-NEXT: movl %esp, %eax -; CHECK-MSVC32-NEXT: pushl 20(%ebp) -; CHECK-MSVC32-NEXT: pushl 16(%ebp) -; CHECK-MSVC32-NEXT: pushl 12(%ebp) -; CHECK-MSVC32-NEXT: pushl 8(%ebp) -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl $0 -; CHECK-MSVC32-NEXT: pushl %eax +; CHECK-MSVC32-NEXT: subl $96, %esp +; CHECK-MSVC32-NEXT: movl 8(%ebp), %eax +; CHECK-MSVC32-NEXT: movl 12(%ebp), %ecx +; CHECK-MSVC32-NEXT: movl 16(%ebp), %edx +; CHECK-MSVC32-NEXT: movl 20(%ebp), %esi +; CHECK-MSVC32-NEXT: movl %esi, 60(%esp) +; CHECK-MSVC32-NEXT: movl %edx, 56(%esp) +; CHECK-MSVC32-NEXT: movl %ecx, 52(%esp) +; CHECK-MSVC32-NEXT: movl %eax, 48(%esp) +; CHECK-MSVC32-NEXT: leal 64(%esp), %eax +; CHECK-MSVC32-NEXT: movl %eax, (%esp) +; CHECK-MSVC32-NEXT: movl $0, 32(%esp) +; CHECK-MSVC32-NEXT: movl $0, 28(%esp) +; CHECK-MSVC32-NEXT: movl $0, 24(%esp) +; CHECK-MSVC32-NEXT: movl $0, 20(%esp) +; CHECK-MSVC32-NEXT: movl $0, 16(%esp) +; CHECK-MSVC32-NEXT: movl $0, 12(%esp) +; CHECK-MSVC32-NEXT: movl $0, 8(%esp) +; CHECK-MSVC32-NEXT: movl $0, 4(%esp) ; CHECK-MSVC32-NEXT: calll _trailing_arg -; CHECK-MSVC32-NEXT: addl $52, %esp -; CHECK-MSVC32-NEXT: movl %ebp, %esp +; CHECK-MSVC32-NEXT: leal -4(%ebp), %esp +; CHECK-MSVC32-NEXT: popl %esi ; CHECK-MSVC32-NEXT: popl %ebp ; CHECK-MSVC32-NEXT: retl call PrimTy @trailing_arg(i64 0, i64 0, i64 0, i64 0, PrimTy %x) diff --git a/llvm/test/CodeGen/X86/i128-sdiv.ll b/llvm/test/CodeGen/X86/i128-sdiv.ll index 717f52f198ee8..7d5757392c982 100644 --- a/llvm/test/CodeGen/X86/i128-sdiv.ll +++ b/llvm/test/CodeGen/X86/i128-sdiv.ll @@ -8,18 +8,21 @@ define i128 @test1(i128 %x) nounwind { ; X86-LABEL: test1: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 36(%ebp), %ecx ; X86-NEXT: movl %ecx, %esi ; X86-NEXT: sarl $31, %esi ; X86-NEXT: movl %esi, %edx ; X86-NEXT: shrl $30, %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl 24(%ebp), %edi ; X86-NEXT: addl %esi, %edi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %esi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %edx +; X86-NEXT: adcl 28(%ebp), %esi +; X86-NEXT: adcl 32(%ebp), %edx ; X86-NEXT: adcl $0, %ecx ; X86-NEXT: shrdl $2, %ecx, %edx ; X86-NEXT: movl %ecx, %esi @@ -29,8 +32,10 @@ define i128 @test1(i128 %x) nounwind { ; X86-NEXT: movl %ecx, 8(%eax) ; X86-NEXT: movl %esi, 4(%eax) ; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: test1: @@ -52,38 +57,44 @@ define i128 @test1(i128 %x) nounwind { define i128 @test2(i128 %x) nounwind { ; X86-LABEL: test2: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl %edx, %esi -; X86-NEXT: sarl $31, %esi -; X86-NEXT: movl %esi, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl %eax, %edx +; X86-NEXT: sarl $31, %edx +; X86-NEXT: movl %edx, %ecx ; X86-NEXT: shrl $30, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: addl %esi, %edi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %esi -; X86-NEXT: adcl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: adcl $0, %edx -; X86-NEXT: shrdl $2, %edx, %ecx -; X86-NEXT: movl %edx, %esi +; X86-NEXT: movl 24(%ebp), %esi +; X86-NEXT: addl %edx, %esi +; X86-NEXT: adcl 28(%ebp), %edx +; X86-NEXT: adcl 32(%ebp), %ecx +; X86-NEXT: adcl $0, %eax +; X86-NEXT: shrdl $2, %eax, %ecx +; X86-NEXT: movl %eax, %esi ; X86-NEXT: sarl $31, %esi -; X86-NEXT: sarl $2, %edx -; X86-NEXT: xorl %edi, %edi +; X86-NEXT: sarl $2, %eax +; X86-NEXT: xorl %edx, %edx ; X86-NEXT: negl %ecx +; X86-NEXT: movl $0, %edi +; X86-NEXT: sbbl %eax, %edi ; X86-NEXT: movl $0, %ebx -; X86-NEXT: sbbl %edx, %ebx -; X86-NEXT: movl $0, %edx +; X86-NEXT: sbbl %esi, %ebx ; X86-NEXT: sbbl %esi, %edx -; X86-NEXT: sbbl %esi, %edi +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %ebx, 4(%eax) -; X86-NEXT: movl %edx, 8(%eax) -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %ebx, 8(%eax) +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: test2: diff --git a/llvm/test/CodeGen/X86/i128-udiv.ll b/llvm/test/CodeGen/X86/i128-udiv.ll index 3f890b7f2443a..9011832421326 100644 --- a/llvm/test/CodeGen/X86/i128-udiv.ll +++ b/llvm/test/CodeGen/X86/i128-udiv.ll @@ -8,15 +8,21 @@ define i128 @test1(i128 %x) nounwind { ; X86-LABEL: test1: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %edx ; X86-NEXT: shrdl $2, %edx, %ecx ; X86-NEXT: shrl $2, %edx ; X86-NEXT: movl %edx, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) ; X86-NEXT: movl $0, 12(%eax) ; X86-NEXT: movl $0, 8(%eax) +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: test1: diff --git a/llvm/test/CodeGen/X86/iabs.ll b/llvm/test/CodeGen/X86/iabs.ll index 55c318e87a5a0..bdceeefbcfaba 100644 --- a/llvm/test/CodeGen/X86/iabs.ll +++ b/llvm/test/CodeGen/X86/iabs.ll @@ -123,31 +123,34 @@ define i64 @test_i64(i64 %a) nounwind { define i128 @test_i128(i128 %a) nounwind { ; X86-LABEL: test_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, %edx -; X86-NEXT: sarl $31, %edx -; X86-NEXT: xorl %edx, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: xorl %edx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: xorl %edx, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: xorl %edx, %ebx -; X86-NEXT: subl %edx, %ebx -; X86-NEXT: sbbl %edx, %edi -; X86-NEXT: sbbl %edx, %esi -; X86-NEXT: sbbl %edx, %ecx -; X86-NEXT: movl %ebx, (%eax) -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: xorl %eax, %ecx +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: xorl %eax, %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: xorl %eax, %esi +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: xorl %eax, %edi +; X86-NEXT: subl %eax, %edi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %eax, %edx +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edi, (%eax) +; X86-NEXT: movl %esi, 4(%eax) +; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: test_i128: diff --git a/llvm/test/CodeGen/X86/icmp-shift-opt.ll b/llvm/test/CodeGen/X86/icmp-shift-opt.ll index c52b3ed6c926d..4a6c1d0ae5deb 100644 --- a/llvm/test/CodeGen/X86/icmp-shift-opt.ll +++ b/llvm/test/CodeGen/X86/icmp-shift-opt.ll @@ -10,33 +10,39 @@ define i128 @opt_setcc_lt_power_of_2(i128 %a) nounwind { ; X86-LABEL: opt_setcc_lt_power_of_2: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %edi +; X86-NEXT: movl 24(%ebp), %esi ; X86-NEXT: .p2align 4 ; X86-NEXT: .LBB0_1: # %loop ; X86-NEXT: # =>This Inner Loop Header: Depth=1 -; X86-NEXT: addl $1, %edi -; X86-NEXT: adcl $0, %esi +; X86-NEXT: addl $1, %esi +; X86-NEXT: adcl $0, %edi ; X86-NEXT: adcl $0, %edx ; X86-NEXT: adcl $0, %ecx ; X86-NEXT: movl %edx, %ebx ; X86-NEXT: orl %ecx, %ebx -; X86-NEXT: movl %esi, %ebp -; X86-NEXT: orl %edx, %ebp -; X86-NEXT: orl %ecx, %ebp -; X86-NEXT: shrdl $28, %ebx, %ebp +; X86-NEXT: movl %esi, %eax +; X86-NEXT: movl %edi, %esi +; X86-NEXT: orl %edx, %esi +; X86-NEXT: orl %ecx, %esi +; X86-NEXT: shrdl $28, %ebx, %esi +; X86-NEXT: movl %eax, %esi ; X86-NEXT: jne .LBB0_1 ; X86-NEXT: # %bb.2: # %exit -; X86-NEXT: movl %edi, (%eax) -; X86-NEXT: movl %esi, 4(%eax) +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %esi, (%eax) +; X86-NEXT: movl %edi, 4(%eax) ; X86-NEXT: movl %edx, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -73,15 +79,21 @@ exit: define i1 @opt_setcc_srl_eq_zero(i128 %a) nounwind { ; X86-LABEL: opt_setcc_srl_eq_zero: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: orl 20(%ebp), %ecx +; X86-NEXT: movl 8(%ebp), %edx ; X86-NEXT: orl %eax, %edx ; X86-NEXT: orl %ecx, %edx ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: shldl $15, %edx, %ecx ; X86-NEXT: sete %al +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; X64-LABEL: opt_setcc_srl_eq_zero: @@ -98,15 +110,21 @@ define i1 @opt_setcc_srl_eq_zero(i128 %a) nounwind { define i1 @opt_setcc_srl_ne_zero(i128 %a) nounwind { ; X86-LABEL: opt_setcc_srl_ne_zero: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: orl 20(%ebp), %ecx +; X86-NEXT: movl 8(%ebp), %edx ; X86-NEXT: orl %eax, %edx ; X86-NEXT: orl %ecx, %edx ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: shldl $15, %edx, %ecx ; X86-NEXT: setne %al +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; X64-LABEL: opt_setcc_srl_ne_zero: @@ -123,13 +141,19 @@ define i1 @opt_setcc_srl_ne_zero(i128 %a) nounwind { define i1 @opt_setcc_shl_eq_zero(i128 %a) nounwind { ; X86-LABEL: opt_setcc_shl_eq_zero: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl 20(%ebp), %ecx ; X86-NEXT: shll $17, %ecx -; X86-NEXT: orl {{[0-9]+}}(%esp), %eax -; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl 8(%ebp), %eax +; X86-NEXT: orl 12(%ebp), %eax ; X86-NEXT: orl %ecx, %eax ; X86-NEXT: sete %al +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; X64-LABEL: opt_setcc_shl_eq_zero: @@ -146,13 +170,19 @@ define i1 @opt_setcc_shl_eq_zero(i128 %a) nounwind { define i1 @opt_setcc_shl_ne_zero(i128 %a) nounwind { ; X86-LABEL: opt_setcc_shl_ne_zero: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl 20(%ebp), %ecx ; X86-NEXT: shll $17, %ecx -; X86-NEXT: orl {{[0-9]+}}(%esp), %eax -; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl 8(%ebp), %eax +; X86-NEXT: orl 12(%ebp), %eax ; X86-NEXT: orl %ecx, %eax ; X86-NEXT: setne %al +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; X64-LABEL: opt_setcc_shl_ne_zero: @@ -170,13 +200,17 @@ define i1 @opt_setcc_shl_ne_zero(i128 %a) nounwind { define i1 @opt_setcc_shl_eq_zero_multiple_shl_users(i128 %a) nounwind { ; X86-LABEL: opt_setcc_shl_eq_zero_multiple_shl_users: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: movl 16(%ebp), %edx +; X86-NEXT: movl 20(%ebp), %esi ; X86-NEXT: shldl $17, %edx, %esi ; X86-NEXT: shldl $17, %ecx, %edx ; X86-NEXT: shldl $17, %eax, %ecx @@ -194,9 +228,11 @@ define i1 @opt_setcc_shl_eq_zero_multiple_shl_users(i128 %a) nounwind { ; X86-NEXT: calll use@PLT ; X86-NEXT: addl $16, %esp ; X86-NEXT: movl %ebx, %eax +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl ; ; X64-LABEL: opt_setcc_shl_eq_zero_multiple_shl_users: diff --git a/llvm/test/CodeGen/X86/kmov.ll b/llvm/test/CodeGen/X86/kmov.ll index cab810d30cd77..8b1e69a97d545 100644 --- a/llvm/test/CodeGen/X86/kmov.ll +++ b/llvm/test/CodeGen/X86/kmov.ll @@ -143,6 +143,57 @@ define <8 x i1> @invert_i8_mask_extract_8(i8 %mask) { ret <8 x i1> %cmp.45 } +define <8 x i1> @i8_mask_extract_7(i8 %mask) { +; X64-AVX512-LABEL: i8_mask_extract_7: +; X64-AVX512: # %bb.0: +; X64-AVX512-NEXT: shrb %dil +; X64-AVX512-NEXT: movzbl %dil, %eax +; X64-AVX512-NEXT: kmovd %eax, %k0 +; X64-AVX512-NEXT: vpmovm2w %k0, %xmm0 +; X64-AVX512-NEXT: retq +; +; X64-KNL-LABEL: i8_mask_extract_7: +; X64-KNL: # %bb.0: +; X64-KNL-NEXT: vmovd %edi, %xmm0 +; X64-KNL-NEXT: vpbroadcastb %xmm0, %xmm0 +; X64-KNL-NEXT: vpbroadcastq {{.*#+}} xmm1 = [2,4,8,16,32,64,128,0,2,4,8,16,32,64,128,0] +; X64-KNL-NEXT: vpand %xmm1, %xmm0, %xmm0 +; X64-KNL-NEXT: vpcmpeqb %xmm1, %xmm0, %xmm0 +; X64-KNL-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; X64-KNL-NEXT: retq + %.splatinsert = insertelement <8 x i8> poison, i8 %mask, i64 0 + %.splat = shufflevector <8 x i8> %.splatinsert, <8 x i8> poison, <8 x i32> zeroinitializer + %1 = and <8 x i8> %.splat, + %cmp.45 = icmp ne <8 x i8> %1, zeroinitializer + ret <8 x i1> %cmp.45 +} + +define <8 x i1> @invert_i8_mask_extract_7(i8 %mask) { +; X64-AVX512-LABEL: invert_i8_mask_extract_7: +; X64-AVX512: # %bb.0: +; X64-AVX512-NEXT: shrb %dil +; X64-AVX512-NEXT: movzbl %dil, %eax +; X64-AVX512-NEXT: kmovd %eax, %k0 +; X64-AVX512-NEXT: knotb %k0, %k0 +; X64-AVX512-NEXT: vpmovm2w %k0, %xmm0 +; X64-AVX512-NEXT: retq +; +; X64-KNL-LABEL: invert_i8_mask_extract_7: +; X64-KNL: # %bb.0: +; X64-KNL-NEXT: vmovd %edi, %xmm0 +; X64-KNL-NEXT: vpbroadcastb %xmm0, %xmm0 +; X64-KNL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-KNL-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; X64-KNL-NEXT: vpcmpeqb %xmm1, %xmm0, %xmm0 +; X64-KNL-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; X64-KNL-NEXT: retq + %.splatinsert = insertelement <8 x i8> poison, i8 %mask, i64 0 + %.splat = shufflevector <8 x i8> %.splatinsert, <8 x i8> poison, <8 x i32> zeroinitializer + %1 = and <8 x i8> %.splat, + %cmp.45 = icmp eq <8 x i8> %1, zeroinitializer + ret <8 x i1> %cmp.45 +} + define <4 x i1> @i16_mask_extract_4(i16 %mask) { ; X64-AVX512-LABEL: i16_mask_extract_4: ; X64-AVX512: # %bb.0: diff --git a/llvm/test/CodeGen/X86/late-tail-dup-computed-goto.mir b/llvm/test/CodeGen/X86/late-tail-dup-computed-goto.mir new file mode 100644 index 0000000000000..e272e7ee3cb0f --- /dev/null +++ b/llvm/test/CodeGen/X86/late-tail-dup-computed-goto.mir @@ -0,0 +1,128 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=tailduplication -tail-dup-pred-size=1 -tail-dup-succ-size=1 %s -o - | FileCheck %s +# +# Check that only the computed gotos are duplicated aggressively. +# +--- | + @computed_goto.dispatch = constant [5 x ptr] [ptr null, ptr blockaddress(@computed_goto, %bb1), ptr blockaddress(@computed_goto, %bb2), ptr blockaddress(@computed_goto, %bb3), ptr blockaddress(@computed_goto, %bb4)] + declare i64 @f0() + declare i64 @f1() + declare i64 @f2() + declare i64 @f3() + declare i64 @f4() + declare i64 @f5() + define void @computed_goto() { + start: + ret void + bb1: + ret void + bb2: + ret void + bb3: + ret void + bb4: + ret void + } + define void @jump_table() { ret void } + define void @jump_table_pic() { ret void } +... +--- +name: computed_goto +alignment: 1 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: computed_goto + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f0, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rax + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[COPY]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64_nosp = COPY [[COPY1]] + ; CHECK-NEXT: JMP64m $noreg, 8, [[COPY2]], @computed_goto.dispatch, $noreg + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1.bb1 (ir-block-address-taken %ir-block.bb1): + ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f1, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gr64 = COPY $rax + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[COPY3]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64_nosp = COPY [[COPY1]] + ; CHECK-NEXT: JMP64m $noreg, 8, [[COPY2]], @computed_goto.dispatch, $noreg + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2.bb2 (ir-block-address-taken %ir-block.bb2): + ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f2, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gr64 = COPY $rax + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[COPY4]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64_nosp = COPY [[COPY1]] + ; CHECK-NEXT: JMP64m $noreg, 8, [[COPY2]], @computed_goto.dispatch, $noreg + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.bb3 (ir-block-address-taken %ir-block.bb3): + ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f3, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gr64 = COPY $rax + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[COPY5]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64_nosp = COPY [[COPY1]] + ; CHECK-NEXT: JMP64m $noreg, 8, [[COPY2]], @computed_goto.dispatch, $noreg + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4.bb4 (ir-block-address-taken %ir-block.bb4): + ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f4, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:gr64 = COPY $rax + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[COPY6]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gr64_nosp = COPY [[COPY1]] + ; CHECK-NEXT: JMP64m $noreg, 8, [[COPY2]], @computed_goto.dispatch, $noreg + bb.0: + successors: %bb.5(0x80000000) + + CALL64pcrel32 target-flags(x86-plt) @f0, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + %0:gr64 = COPY $rax + %6:gr64_nosp = COPY %0 + JMP_1 %bb.5 + + bb.1.bb1 (ir-block-address-taken %ir-block.bb1): + successors: %bb.5(0x80000000) + + CALL64pcrel32 target-flags(x86-plt) @f1, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + %1:gr64 = COPY $rax + %6:gr64_nosp = COPY %1 + JMP_1 %bb.5 + + bb.2.bb2 (ir-block-address-taken %ir-block.bb2): + successors: %bb.5(0x80000000) + + CALL64pcrel32 target-flags(x86-plt) @f2, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + %2:gr64 = COPY $rax + %6:gr64_nosp = COPY %2 + JMP_1 %bb.5 + + bb.3.bb3 (ir-block-address-taken %ir-block.bb3): + successors: %bb.5(0x80000000) + + CALL64pcrel32 target-flags(x86-plt) @f3, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + %3:gr64 = COPY $rax + %6:gr64_nosp = COPY %3 + JMP_1 %bb.5 + + bb.4.bb4 (ir-block-address-taken %ir-block.bb4): + successors: %bb.5(0x80000000) + + CALL64pcrel32 target-flags(x86-plt) @f4, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax + %4:gr64 = COPY $rax + %6:gr64_nosp = COPY %4 + + bb.5: + successors: %bb.1(0x20000000), %bb.2(0x20000000), %bb.3(0x20000000), %bb.4(0x20000000) + + %5:gr64_nosp = COPY %6 + JMP64m $noreg, 8, %5, @computed_goto.dispatch, $noreg +... diff --git a/llvm/test/CodeGen/X86/mul128.ll b/llvm/test/CodeGen/X86/mul128.ll index fc1cc1f65627a..e10e48f9aea08 100644 --- a/llvm/test/CodeGen/X86/mul128.ll +++ b/llvm/test/CodeGen/X86/mul128.ll @@ -18,85 +18,80 @@ define i128 @foo(i128 %t, i128 %u) { ; X86: # %bb.0: ; X86-NEXT: pushl %ebp ; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp ; X86-NEXT: pushl %ebx -; X86-NEXT: .cfi_def_cfa_offset 12 ; X86-NEXT: pushl %edi -; X86-NEXT: .cfi_def_cfa_offset 16 ; X86-NEXT: pushl %esi -; X86-NEXT: .cfi_def_cfa_offset 20 -; X86-NEXT: subl $8, %esp -; X86-NEXT: .cfi_def_cfa_offset 28 +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp ; X86-NEXT: .cfi_offset %esi, -20 ; X86-NEXT: .cfi_offset %edi, -16 ; X86-NEXT: .cfi_offset %ebx, -12 -; X86-NEXT: .cfi_offset %ebp, -8 -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: imull %ecx, %ebp -; X86-NEXT: movl %eax, %esi +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl 40(%ebp), %edi +; X86-NEXT: movl 44(%ebp), %esi +; X86-NEXT: imull %ecx, %esi +; X86-NEXT: movl %edi, %eax ; X86-NEXT: mull %ecx -; X86-NEXT: movl %eax, %edi +; X86-NEXT: movl %eax, (%esp) # 4-byte Spill ; X86-NEXT: movl %edx, %ebx -; X86-NEXT: addl %ebp, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: imull %esi, %eax +; X86-NEXT: addl %esi, %ebx +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: imull %edi, %eax ; X86-NEXT: addl %eax, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %eax, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: imull %ecx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: mull %ebp -; X86-NEXT: addl %esi, %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: imull %ebp, %esi +; X86-NEXT: movl 48(%ebp), %eax +; X86-NEXT: movl %eax, %ecx +; X86-NEXT: imull 28(%ebp), %ecx +; X86-NEXT: movl 24(%ebp), %edi +; X86-NEXT: mull %edi +; X86-NEXT: addl %ecx, %edx +; X86-NEXT: movl 52(%ebp), %esi +; X86-NEXT: imull %edi, %esi ; X86-NEXT: addl %edx, %esi -; X86-NEXT: addl %edi, %eax -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: addl (%esp), %eax # 4-byte Folded Reload +; X86-NEXT: movl %eax, (%esp) # 4-byte Spill ; X86-NEXT: adcl %ebx, %esi -; X86-NEXT: movl %ebp, %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: mull %edi +; X86-NEXT: movl %edi, %eax +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: mull %ecx ; X86-NEXT: movl %edx, %ebx -; X86-NEXT: movl %eax, (%esp) # 4-byte Spill -; X86-NEXT: movl %ecx, %eax -; X86-NEXT: mull %edi +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: mull %ecx ; X86-NEXT: movl %edx, %edi ; X86-NEXT: movl %eax, %ecx ; X86-NEXT: addl %ebx, %ecx ; X86-NEXT: adcl $0, %edi -; X86-NEXT: movl %ebp, %eax -; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: movl %edx, %ebp -; X86-NEXT: movl %eax, %ebx -; X86-NEXT: addl %ecx, %ebx -; X86-NEXT: adcl %edi, %ebp +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: mull 44(%ebp) +; X86-NEXT: movl %edx, %ebx +; X86-NEXT: addl %ecx, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: adcl %edi, %ebx ; X86-NEXT: setb %cl -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: addl %ebp, %eax +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: mull 44(%ebp) +; X86-NEXT: addl %ebx, %eax ; X86-NEXT: movzbl %cl, %ecx ; X86-NEXT: adcl %ecx, %edx -; X86-NEXT: addl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload +; X86-NEXT: addl (%esp), %eax # 4-byte Folded Reload ; X86-NEXT: adcl %esi, %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ebx, 4(%ecx) -; X86-NEXT: movl (%esp), %esi # 4-byte Reload +; X86-NEXT: movl 8(%ebp), %ecx +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload +; X86-NEXT: movl %esi, 4(%ecx) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload ; X86-NEXT: movl %esi, (%ecx) ; X86-NEXT: movl %eax, 8(%ecx) ; X86-NEXT: movl %edx, 12(%ecx) ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: addl $8, %esp -; X86-NEXT: .cfi_def_cfa_offset 20 +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi -; X86-NEXT: .cfi_def_cfa_offset 16 ; X86-NEXT: popl %edi -; X86-NEXT: .cfi_def_cfa_offset 12 ; X86-NEXT: popl %ebx -; X86-NEXT: .cfi_def_cfa_offset 8 ; X86-NEXT: popl %ebp -; X86-NEXT: .cfi_def_cfa_offset 4 +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl $4 %k = mul i128 %t, %u ret i128 %k diff --git a/llvm/test/CodeGen/X86/neg-abs.ll b/llvm/test/CodeGen/X86/neg-abs.ll index 961205c50d976..724b2dc4c431a 100644 --- a/llvm/test/CodeGen/X86/neg-abs.ll +++ b/llvm/test/CodeGen/X86/neg-abs.ll @@ -105,31 +105,35 @@ define i128 @neg_abs_i128(i128 %x) nounwind { ; X86-LABEL: neg_abs_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edx, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl %eax, %ecx ; X86-NEXT: sarl $31, %ecx +; X86-NEXT: xorl %ecx, %eax +; X86-NEXT: movl 32(%ebp), %edx ; X86-NEXT: xorl %ecx, %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl 28(%ebp), %esi ; X86-NEXT: xorl %ecx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl 24(%ebp), %edi ; X86-NEXT: xorl %ecx, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: xorl %ecx, %ebx -; X86-NEXT: movl %ecx, %ebp -; X86-NEXT: subl %ebx, %ebp ; X86-NEXT: movl %ecx, %ebx -; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: subl %edi, %ebx ; X86-NEXT: movl %ecx, %edi ; X86-NEXT: sbbl %esi, %edi -; X86-NEXT: sbbl %edx, %ecx -; X86-NEXT: movl %ebp, (%eax) -; X86-NEXT: movl %ebx, 4(%eax) -; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: movl %ecx, %esi +; X86-NEXT: sbbl %edx, %esi +; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, (%eax) +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %esi, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -259,37 +263,42 @@ define i64 @sub_abs_i64(i64 %x, i64 %y) nounwind { define i128 @sub_abs_i128(i128 %x, i128 %y) nounwind { ; X86-LABEL: sub_abs_i128: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 36(%ebp), %eax ; X86-NEXT: movl %eax, %edx ; X86-NEXT: sarl $31, %edx ; X86-NEXT: xorl %edx, %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl 32(%ebp), %ecx ; X86-NEXT: xorl %edx, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl 28(%ebp), %esi ; X86-NEXT: xorl %edx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl 24(%ebp), %edi ; X86-NEXT: xorl %edx, %edi ; X86-NEXT: subl %edx, %edi ; X86-NEXT: sbbl %edx, %esi ; X86-NEXT: sbbl %edx, %ecx ; X86-NEXT: sbbl %edx, %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movl 40(%ebp), %edx ; X86-NEXT: subl %edi, %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl 44(%ebp), %edi ; X86-NEXT: sbbl %esi, %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl 48(%ebp), %esi ; X86-NEXT: sbbl %ecx, %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl 52(%ebp), %ecx ; X86-NEXT: sbbl %eax, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %edx, (%eax) ; X86-NEXT: movl %edi, 4(%eax) ; X86-NEXT: movl %esi, 8(%eax) ; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 ; ; X64-LABEL: sub_abs_i128: diff --git a/llvm/test/CodeGen/X86/popcnt.ll b/llvm/test/CodeGen/X86/popcnt.ll index 35c7c0e09f394..3004b8b72fcc5 100644 --- a/llvm/test/CodeGen/X86/popcnt.ll +++ b/llvm/test/CodeGen/X86/popcnt.ll @@ -340,84 +340,87 @@ define i64 @cnt64(i64 %x) nounwind readnone { define i128 @cnt128(i128 %x) nounwind readnone { ; X86-NOSSE-LABEL: cnt128: ; X86-NOSSE: # %bb.0: -; X86-NOSSE-NEXT: pushl %ebx +; X86-NOSSE-NEXT: pushl %ebp +; X86-NOSSE-NEXT: movl %esp, %ebp ; X86-NOSSE-NEXT: pushl %edi ; X86-NOSSE-NEXT: pushl %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: shrl %ebx -; X86-NOSSE-NEXT: andl $1431655765, %ebx # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %ebx, %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: andl $858993459, %ebx # imm = 0x33333333 -; X86-NOSSE-NEXT: shrl $2, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %ebx, %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: shrl $4, %ebx -; X86-NOSSE-NEXT: addl %edi, %ebx -; X86-NOSSE-NEXT: andl $252645135, %ebx # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %ebx, %edi # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: shrl %ebx -; X86-NOSSE-NEXT: andl $1431655765, %ebx # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %ebx, %esi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: andl $858993459, %ebx # imm = 0x33333333 +; X86-NOSSE-NEXT: andl $-16, %esp +; X86-NOSSE-NEXT: movl 24(%ebp), %eax +; X86-NOSSE-NEXT: movl 32(%ebp), %ecx +; X86-NOSSE-NEXT: movl 36(%ebp), %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl %edx +; X86-NOSSE-NEXT: andl $1431655765, %edx # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 ; X86-NOSSE-NEXT: shrl $2, %esi ; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %ebx, %esi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: shrl $4, %ebx -; X86-NOSSE-NEXT: addl %esi, %ebx -; X86-NOSSE-NEXT: andl $252645135, %ebx # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %ebx, %esi # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %esi -; X86-NOSSE-NEXT: addl %edi, %esi -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: shrl %edi -; X86-NOSSE-NEXT: andl $1431655765, %edi # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %edi, %edx -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 -; X86-NOSSE-NEXT: shrl $2, %edx -; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %edi, %edx -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: shrl $4, %edi -; X86-NOSSE-NEXT: addl %edx, %edi -; X86-NOSSE-NEXT: andl $252645135, %edi # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %edi, %edx # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edx -; X86-NOSSE-NEXT: movl %ecx, %edi -; X86-NOSSE-NEXT: shrl %edi -; X86-NOSSE-NEXT: andl $1431655765, %edi # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %edi, %ecx -; X86-NOSSE-NEXT: movl %ecx, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl $4, %edx +; X86-NOSSE-NEXT: addl %esi, %edx +; X86-NOSSE-NEXT: movl %ecx, %esi +; X86-NOSSE-NEXT: shrl %esi +; X86-NOSSE-NEXT: andl $1431655765, %esi # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %esi, %ecx +; X86-NOSSE-NEXT: movl %ecx, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 ; X86-NOSSE-NEXT: shrl $2, %ecx ; X86-NOSSE-NEXT: andl $858993459, %ecx # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %edi, %ecx +; X86-NOSSE-NEXT: addl %esi, %ecx ; X86-NOSSE-NEXT: movl %ecx, %edi ; X86-NOSSE-NEXT: shrl $4, %edi ; X86-NOSSE-NEXT: addl %ecx, %edi +; X86-NOSSE-NEXT: movl 28(%ebp), %esi +; X86-NOSSE-NEXT: andl $252645135, %edx # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %edx, %edx # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edx ; X86-NOSSE-NEXT: andl $252645135, %edi # imm = 0xF0F0F0F ; X86-NOSSE-NEXT: imull $16843009, %edi, %ecx # imm = 0x1010101 ; X86-NOSSE-NEXT: shrl $24, %ecx ; X86-NOSSE-NEXT: addl %edx, %ecx -; X86-NOSSE-NEXT: addl %esi, %ecx -; X86-NOSSE-NEXT: movl %ecx, (%eax) +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl %edx +; X86-NOSSE-NEXT: andl $1431655765, %edx # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 +; X86-NOSSE-NEXT: shrl $2, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl $4, %edx +; X86-NOSSE-NEXT: addl %esi, %edx +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: shrl %esi +; X86-NOSSE-NEXT: andl $1431655765, %esi # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %esi, %eax +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 +; X86-NOSSE-NEXT: shrl $2, %eax +; X86-NOSSE-NEXT: andl $858993459, %eax # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %esi, %eax +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: shrl $4, %esi +; X86-NOSSE-NEXT: addl %eax, %esi +; X86-NOSSE-NEXT: andl $252645135, %edx # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %edx, %eax # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %eax +; X86-NOSSE-NEXT: andl $252645135, %esi # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %esi, %edx # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edx +; X86-NOSSE-NEXT: addl %eax, %edx +; X86-NOSSE-NEXT: addl %ecx, %edx +; X86-NOSSE-NEXT: movl 8(%ebp), %eax +; X86-NOSSE-NEXT: movl %edx, (%eax) ; X86-NOSSE-NEXT: movl $0, 12(%eax) ; X86-NOSSE-NEXT: movl $0, 8(%eax) ; X86-NOSSE-NEXT: movl $0, 4(%eax) +; X86-NOSSE-NEXT: leal -8(%ebp), %esp ; X86-NOSSE-NEXT: popl %esi ; X86-NOSSE-NEXT: popl %edi -; X86-NOSSE-NEXT: popl %ebx +; X86-NOSSE-NEXT: popl %ebp ; X86-NOSSE-NEXT: retl $4 ; ; X64-BASE-LABEL: cnt128: @@ -462,20 +465,26 @@ define i128 @cnt128(i128 %x) nounwind readnone { ; ; X86-POPCNT-LABEL: cnt128: ; X86-POPCNT: # %bb.0: +; X86-POPCNT-NEXT: pushl %ebp +; X86-POPCNT-NEXT: movl %esp, %ebp ; X86-POPCNT-NEXT: pushl %esi -; X86-POPCNT-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %edx +; X86-POPCNT-NEXT: andl $-16, %esp +; X86-POPCNT-NEXT: subl $16, %esp +; X86-POPCNT-NEXT: movl 8(%ebp), %eax +; X86-POPCNT-NEXT: popcntl 36(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 32(%ebp), %edx ; X86-POPCNT-NEXT: addl %ecx, %edx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %esi +; X86-POPCNT-NEXT: popcntl 28(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 24(%ebp), %esi ; X86-POPCNT-NEXT: addl %ecx, %esi ; X86-POPCNT-NEXT: addl %edx, %esi ; X86-POPCNT-NEXT: movl %esi, (%eax) ; X86-POPCNT-NEXT: movl $0, 12(%eax) ; X86-POPCNT-NEXT: movl $0, 8(%eax) ; X86-POPCNT-NEXT: movl $0, 4(%eax) +; X86-POPCNT-NEXT: leal -4(%ebp), %esp ; X86-POPCNT-NEXT: popl %esi +; X86-POPCNT-NEXT: popl %ebp ; X86-POPCNT-NEXT: retl $4 ; ; X64-POPCNT-LABEL: cnt128: @@ -522,7 +531,11 @@ define i128 @cnt128(i128 %x) nounwind readnone { ; ; X86-SSE2-LABEL: cnt128: ; X86-SSE2: # %bb.0: -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: pushl %ebp +; X86-SSE2-NEXT: movl %esp, %ebp +; X86-SSE2-NEXT: andl $-16, %esp +; X86-SSE2-NEXT: subl $16, %esp +; X86-SSE2-NEXT: movl 8(%ebp), %eax ; X86-SSE2-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSE2-NEXT: movdqa %xmm2, %xmm0 ; X86-SSE2-NEXT: psrlw $1, %xmm0 @@ -564,11 +577,17 @@ define i128 @cnt128(i128 %x) nounwind readnone { ; X86-SSE2-NEXT: movl $0, 12(%eax) ; X86-SSE2-NEXT: movl $0, 8(%eax) ; X86-SSE2-NEXT: movl $0, 4(%eax) +; X86-SSE2-NEXT: movl %ebp, %esp +; X86-SSE2-NEXT: popl %ebp ; X86-SSE2-NEXT: retl $4 ; ; X86-SSSE3-LABEL: cnt128: ; X86-SSSE3: # %bb.0: -; X86-SSSE3-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSSE3-NEXT: pushl %ebp +; X86-SSSE3-NEXT: movl %esp, %ebp +; X86-SSSE3-NEXT: andl $-16, %esp +; X86-SSSE3-NEXT: subl $16, %esp +; X86-SSSE3-NEXT: movl 8(%ebp), %eax ; X86-SSSE3-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; X86-SSSE3-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSSE3-NEXT: movdqa %xmm2, %xmm3 @@ -600,6 +619,8 @@ define i128 @cnt128(i128 %x) nounwind readnone { ; X86-SSSE3-NEXT: movl $0, 12(%eax) ; X86-SSSE3-NEXT: movl $0, 8(%eax) ; X86-SSSE3-NEXT: movl $0, 4(%eax) +; X86-SSSE3-NEXT: movl %ebp, %esp +; X86-SSSE3-NEXT: popl %ebp ; X86-SSSE3-NEXT: retl $4 %cnt = tail call i128 @llvm.ctpop.i128(i128 %x) ret i128 %cnt @@ -928,87 +949,92 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; X86-NOSSE-LABEL: cnt128_optsize: ; X86-NOSSE: # %bb.0: ; X86-NOSSE-NEXT: pushl %ebp +; X86-NOSSE-NEXT: movl %esp, %ebp ; X86-NOSSE-NEXT: pushl %ebx ; X86-NOSSE-NEXT: pushl %edi ; X86-NOSSE-NEXT: pushl %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NOSSE-NEXT: movl %ebx, %ecx -; X86-NOSSE-NEXT: shrl %ecx -; X86-NOSSE-NEXT: movl $1431655765, %edi # imm = 0x55555555 -; X86-NOSSE-NEXT: andl %edi, %ecx -; X86-NOSSE-NEXT: subl %ecx, %ebx +; X86-NOSSE-NEXT: andl $-16, %esp +; X86-NOSSE-NEXT: subl $16, %esp +; X86-NOSSE-NEXT: movl 32(%ebp), %edx +; X86-NOSSE-NEXT: movl 36(%ebp), %esi +; X86-NOSSE-NEXT: movl %esi, %eax +; X86-NOSSE-NEXT: shrl %eax +; X86-NOSSE-NEXT: movl $1431655765, %ecx # imm = 0x55555555 +; X86-NOSSE-NEXT: andl %ecx, %eax +; X86-NOSSE-NEXT: subl %eax, %esi ; X86-NOSSE-NEXT: movl $858993459, %ecx # imm = 0x33333333 -; X86-NOSSE-NEXT: movl %ebx, %ebp -; X86-NOSSE-NEXT: andl %ecx, %ebp +; X86-NOSSE-NEXT: movl %esi, %edi +; X86-NOSSE-NEXT: andl %ecx, %edi +; X86-NOSSE-NEXT: shrl $2, %esi +; X86-NOSSE-NEXT: andl %ecx, %esi +; X86-NOSSE-NEXT: addl %edi, %esi +; X86-NOSSE-NEXT: movl %esi, %edi +; X86-NOSSE-NEXT: shrl $4, %edi +; X86-NOSSE-NEXT: addl %esi, %edi +; X86-NOSSE-NEXT: movl %edx, %esi +; X86-NOSSE-NEXT: shrl %esi +; X86-NOSSE-NEXT: movl $1431655765, %eax # imm = 0x55555555 +; X86-NOSSE-NEXT: andl %eax, %esi +; X86-NOSSE-NEXT: subl %esi, %edx +; X86-NOSSE-NEXT: movl %edx, %esi +; X86-NOSSE-NEXT: andl %ecx, %esi +; X86-NOSSE-NEXT: shrl $2, %edx +; X86-NOSSE-NEXT: andl %ecx, %edx +; X86-NOSSE-NEXT: addl %esi, %edx +; X86-NOSSE-NEXT: movl %edx, %ebx +; X86-NOSSE-NEXT: shrl $4, %ebx +; X86-NOSSE-NEXT: addl %edx, %ebx +; X86-NOSSE-NEXT: movl $252645135, %edx # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: andl %edx, %edi +; X86-NOSSE-NEXT: imull $16843009, %edi, %edi # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edi +; X86-NOSSE-NEXT: andl %edx, %ebx +; X86-NOSSE-NEXT: imull $16843009, %ebx, %edx # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edx +; X86-NOSSE-NEXT: addl %edi, %edx +; X86-NOSSE-NEXT: movl 28(%ebp), %ebx +; X86-NOSSE-NEXT: movl %ebx, %edi +; X86-NOSSE-NEXT: shrl %edi +; X86-NOSSE-NEXT: andl %eax, %edi +; X86-NOSSE-NEXT: subl %edi, %ebx +; X86-NOSSE-NEXT: movl %ebx, %edi +; X86-NOSSE-NEXT: andl %ecx, %edi ; X86-NOSSE-NEXT: shrl $2, %ebx ; X86-NOSSE-NEXT: andl %ecx, %ebx -; X86-NOSSE-NEXT: addl %ebp, %ebx -; X86-NOSSE-NEXT: movl %ebx, %ebp -; X86-NOSSE-NEXT: shrl $4, %ebp -; X86-NOSSE-NEXT: addl %ebx, %ebp +; X86-NOSSE-NEXT: addl %edi, %ebx +; X86-NOSSE-NEXT: movl %ebx, %edi +; X86-NOSSE-NEXT: shrl $4, %edi +; X86-NOSSE-NEXT: addl %ebx, %edi +; X86-NOSSE-NEXT: movl 24(%ebp), %eax ; X86-NOSSE-NEXT: movl %eax, %ebx ; X86-NOSSE-NEXT: shrl %ebx -; X86-NOSSE-NEXT: andl %edi, %ebx +; X86-NOSSE-NEXT: movl $1431655765, %esi # imm = 0x55555555 +; X86-NOSSE-NEXT: andl %esi, %ebx ; X86-NOSSE-NEXT: subl %ebx, %eax ; X86-NOSSE-NEXT: movl %eax, %ebx ; X86-NOSSE-NEXT: andl %ecx, %ebx ; X86-NOSSE-NEXT: shrl $2, %eax ; X86-NOSSE-NEXT: andl %ecx, %eax ; X86-NOSSE-NEXT: addl %ebx, %eax -; X86-NOSSE-NEXT: movl %eax, %edi -; X86-NOSSE-NEXT: shrl $4, %edi -; X86-NOSSE-NEXT: addl %eax, %edi -; X86-NOSSE-NEXT: movl $252645135, %ebx # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: andl %ebx, %ebp -; X86-NOSSE-NEXT: imull $16843009, %ebp, %eax # imm = 0x1010101 +; X86-NOSSE-NEXT: movl %eax, %ecx +; X86-NOSSE-NEXT: shrl $4, %ecx +; X86-NOSSE-NEXT: addl %eax, %ecx +; X86-NOSSE-NEXT: movl $252645135, %eax # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: andl %eax, %edi +; X86-NOSSE-NEXT: andl %eax, %ecx +; X86-NOSSE-NEXT: imull $16843009, %edi, %eax # imm = 0x1010101 ; X86-NOSSE-NEXT: shrl $24, %eax -; X86-NOSSE-NEXT: andl %ebx, %edi -; X86-NOSSE-NEXT: imull $16843009, %edi, %edi # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edi -; X86-NOSSE-NEXT: addl %eax, %edi -; X86-NOSSE-NEXT: movl %esi, %eax -; X86-NOSSE-NEXT: shrl %eax -; X86-NOSSE-NEXT: movl $1431655765, %ebp # imm = 0x55555555 -; X86-NOSSE-NEXT: andl %ebp, %eax -; X86-NOSSE-NEXT: subl %eax, %esi -; X86-NOSSE-NEXT: movl %esi, %eax -; X86-NOSSE-NEXT: andl %ecx, %eax -; X86-NOSSE-NEXT: shrl $2, %esi -; X86-NOSSE-NEXT: andl %ecx, %esi -; X86-NOSSE-NEXT: addl %eax, %esi -; X86-NOSSE-NEXT: movl %esi, %ebp -; X86-NOSSE-NEXT: shrl $4, %ebp -; X86-NOSSE-NEXT: addl %esi, %ebp -; X86-NOSSE-NEXT: movl %edx, %eax -; X86-NOSSE-NEXT: shrl %eax -; X86-NOSSE-NEXT: movl $1431655765, %esi # imm = 0x55555555 -; X86-NOSSE-NEXT: andl %esi, %eax -; X86-NOSSE-NEXT: subl %eax, %edx -; X86-NOSSE-NEXT: movl %edx, %eax -; X86-NOSSE-NEXT: andl %ecx, %eax -; X86-NOSSE-NEXT: shrl $2, %edx -; X86-NOSSE-NEXT: andl %ecx, %edx -; X86-NOSSE-NEXT: addl %eax, %edx -; X86-NOSSE-NEXT: movl %edx, %eax -; X86-NOSSE-NEXT: shrl $4, %eax -; X86-NOSSE-NEXT: addl %edx, %eax -; X86-NOSSE-NEXT: andl %ebx, %ebp -; X86-NOSSE-NEXT: andl %ebx, %eax -; X86-NOSSE-NEXT: imull $16843009, %ebp, %ecx # imm = 0x1010101 +; X86-NOSSE-NEXT: imull $16843009, %ecx, %ecx # imm = 0x1010101 ; X86-NOSSE-NEXT: shrl $24, %ecx -; X86-NOSSE-NEXT: imull $16843009, %eax, %edx # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edx -; X86-NOSSE-NEXT: addl %ecx, %edx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NOSSE-NEXT: addl %edi, %edx -; X86-NOSSE-NEXT: xorl %ecx, %ecx -; X86-NOSSE-NEXT: movl %ecx, 12(%eax) -; X86-NOSSE-NEXT: movl %ecx, 8(%eax) -; X86-NOSSE-NEXT: movl %ecx, 4(%eax) -; X86-NOSSE-NEXT: movl %edx, (%eax) +; X86-NOSSE-NEXT: addl %eax, %ecx +; X86-NOSSE-NEXT: movl 8(%ebp), %eax +; X86-NOSSE-NEXT: addl %edx, %ecx +; X86-NOSSE-NEXT: xorl %edx, %edx +; X86-NOSSE-NEXT: movl %edx, 12(%eax) +; X86-NOSSE-NEXT: movl %edx, 8(%eax) +; X86-NOSSE-NEXT: movl %edx, 4(%eax) +; X86-NOSSE-NEXT: movl %ecx, (%eax) +; X86-NOSSE-NEXT: leal -12(%ebp), %esp ; X86-NOSSE-NEXT: popl %esi ; X86-NOSSE-NEXT: popl %edi ; X86-NOSSE-NEXT: popl %ebx @@ -1057,13 +1083,17 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; ; X86-POPCNT-LABEL: cnt128_optsize: ; X86-POPCNT: # %bb.0: +; X86-POPCNT-NEXT: pushl %ebp +; X86-POPCNT-NEXT: movl %esp, %ebp ; X86-POPCNT-NEXT: pushl %esi -; X86-POPCNT-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %edx +; X86-POPCNT-NEXT: andl $-16, %esp +; X86-POPCNT-NEXT: subl $16, %esp +; X86-POPCNT-NEXT: movl 8(%ebp), %eax +; X86-POPCNT-NEXT: popcntl 36(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 32(%ebp), %edx ; X86-POPCNT-NEXT: addl %ecx, %edx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %esi +; X86-POPCNT-NEXT: popcntl 28(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 24(%ebp), %esi ; X86-POPCNT-NEXT: addl %ecx, %esi ; X86-POPCNT-NEXT: addl %edx, %esi ; X86-POPCNT-NEXT: xorl %ecx, %ecx @@ -1071,7 +1101,9 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; X86-POPCNT-NEXT: movl %ecx, 8(%eax) ; X86-POPCNT-NEXT: movl %ecx, 4(%eax) ; X86-POPCNT-NEXT: movl %esi, (%eax) +; X86-POPCNT-NEXT: leal -4(%ebp), %esp ; X86-POPCNT-NEXT: popl %esi +; X86-POPCNT-NEXT: popl %ebp ; X86-POPCNT-NEXT: retl $4 ; ; X64-POPCNT-LABEL: cnt128_optsize: @@ -1118,7 +1150,11 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; ; X86-SSE2-LABEL: cnt128_optsize: ; X86-SSE2: # %bb.0: -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: pushl %ebp +; X86-SSE2-NEXT: movl %esp, %ebp +; X86-SSE2-NEXT: andl $-16, %esp +; X86-SSE2-NEXT: subl $16, %esp +; X86-SSE2-NEXT: movl 8(%ebp), %eax ; X86-SSE2-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSE2-NEXT: movdqa %xmm2, %xmm0 ; X86-SSE2-NEXT: psrlw $1, %xmm0 @@ -1161,11 +1197,17 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; X86-SSE2-NEXT: movl %ecx, 8(%eax) ; X86-SSE2-NEXT: movl %ecx, 4(%eax) ; X86-SSE2-NEXT: movl %edx, (%eax) +; X86-SSE2-NEXT: movl %ebp, %esp +; X86-SSE2-NEXT: popl %ebp ; X86-SSE2-NEXT: retl $4 ; ; X86-SSSE3-LABEL: cnt128_optsize: ; X86-SSSE3: # %bb.0: -; X86-SSSE3-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSSE3-NEXT: pushl %ebp +; X86-SSSE3-NEXT: movl %esp, %ebp +; X86-SSSE3-NEXT: andl $-16, %esp +; X86-SSSE3-NEXT: subl $16, %esp +; X86-SSSE3-NEXT: movl 8(%ebp), %eax ; X86-SSSE3-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; X86-SSSE3-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSSE3-NEXT: movdqa %xmm2, %xmm3 @@ -1198,6 +1240,8 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ; X86-SSSE3-NEXT: movl %ecx, 8(%eax) ; X86-SSSE3-NEXT: movl %ecx, 4(%eax) ; X86-SSSE3-NEXT: movl %edx, (%eax) +; X86-SSSE3-NEXT: movl %ebp, %esp +; X86-SSSE3-NEXT: popl %ebp ; X86-SSSE3-NEXT: retl $4 %cnt = tail call i128 @llvm.ctpop.i128(i128 %x) ret i128 %cnt @@ -1415,85 +1459,88 @@ define i64 @cnt64_pgso(i64 %x) nounwind readnone !prof !14 { define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; X86-NOSSE-LABEL: cnt128_pgso: ; X86-NOSSE: # %bb.0: -; X86-NOSSE-NEXT: pushl %ebx +; X86-NOSSE-NEXT: pushl %ebp +; X86-NOSSE-NEXT: movl %esp, %ebp ; X86-NOSSE-NEXT: pushl %edi ; X86-NOSSE-NEXT: pushl %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: shrl %ebx -; X86-NOSSE-NEXT: andl $1431655765, %ebx # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %ebx, %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: andl $858993459, %ebx # imm = 0x33333333 -; X86-NOSSE-NEXT: shrl $2, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %ebx, %edi -; X86-NOSSE-NEXT: movl %edi, %ebx -; X86-NOSSE-NEXT: shrl $4, %ebx -; X86-NOSSE-NEXT: addl %edi, %ebx -; X86-NOSSE-NEXT: andl $252645135, %ebx # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %ebx, %edi # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: shrl %ebx -; X86-NOSSE-NEXT: andl $1431655765, %ebx # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %ebx, %esi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: andl $858993459, %ebx # imm = 0x33333333 +; X86-NOSSE-NEXT: andl $-16, %esp +; X86-NOSSE-NEXT: movl 24(%ebp), %eax +; X86-NOSSE-NEXT: movl 32(%ebp), %ecx +; X86-NOSSE-NEXT: movl 36(%ebp), %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl %edx +; X86-NOSSE-NEXT: andl $1431655765, %edx # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 ; X86-NOSSE-NEXT: shrl $2, %esi ; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %ebx, %esi -; X86-NOSSE-NEXT: movl %esi, %ebx -; X86-NOSSE-NEXT: shrl $4, %ebx -; X86-NOSSE-NEXT: addl %esi, %ebx -; X86-NOSSE-NEXT: andl $252645135, %ebx # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %ebx, %esi # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %esi -; X86-NOSSE-NEXT: addl %edi, %esi -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: shrl %edi -; X86-NOSSE-NEXT: andl $1431655765, %edi # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %edi, %edx -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 -; X86-NOSSE-NEXT: shrl $2, %edx -; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %edi, %edx -; X86-NOSSE-NEXT: movl %edx, %edi -; X86-NOSSE-NEXT: shrl $4, %edi -; X86-NOSSE-NEXT: addl %edx, %edi -; X86-NOSSE-NEXT: andl $252645135, %edi # imm = 0xF0F0F0F -; X86-NOSSE-NEXT: imull $16843009, %edi, %edx # imm = 0x1010101 -; X86-NOSSE-NEXT: shrl $24, %edx -; X86-NOSSE-NEXT: movl %ecx, %edi -; X86-NOSSE-NEXT: shrl %edi -; X86-NOSSE-NEXT: andl $1431655765, %edi # imm = 0x55555555 -; X86-NOSSE-NEXT: subl %edi, %ecx -; X86-NOSSE-NEXT: movl %ecx, %edi -; X86-NOSSE-NEXT: andl $858993459, %edi # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl $4, %edx +; X86-NOSSE-NEXT: addl %esi, %edx +; X86-NOSSE-NEXT: movl %ecx, %esi +; X86-NOSSE-NEXT: shrl %esi +; X86-NOSSE-NEXT: andl $1431655765, %esi # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %esi, %ecx +; X86-NOSSE-NEXT: movl %ecx, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 ; X86-NOSSE-NEXT: shrl $2, %ecx ; X86-NOSSE-NEXT: andl $858993459, %ecx # imm = 0x33333333 -; X86-NOSSE-NEXT: addl %edi, %ecx +; X86-NOSSE-NEXT: addl %esi, %ecx ; X86-NOSSE-NEXT: movl %ecx, %edi ; X86-NOSSE-NEXT: shrl $4, %edi ; X86-NOSSE-NEXT: addl %ecx, %edi +; X86-NOSSE-NEXT: movl 28(%ebp), %esi +; X86-NOSSE-NEXT: andl $252645135, %edx # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %edx, %edx # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edx ; X86-NOSSE-NEXT: andl $252645135, %edi # imm = 0xF0F0F0F ; X86-NOSSE-NEXT: imull $16843009, %edi, %ecx # imm = 0x1010101 ; X86-NOSSE-NEXT: shrl $24, %ecx ; X86-NOSSE-NEXT: addl %edx, %ecx -; X86-NOSSE-NEXT: addl %esi, %ecx -; X86-NOSSE-NEXT: xorl %edx, %edx -; X86-NOSSE-NEXT: movl %edx, 12(%eax) -; X86-NOSSE-NEXT: movl %edx, 8(%eax) -; X86-NOSSE-NEXT: movl %edx, 4(%eax) -; X86-NOSSE-NEXT: movl %ecx, (%eax) +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl %edx +; X86-NOSSE-NEXT: andl $1431655765, %edx # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: andl $858993459, %edx # imm = 0x33333333 +; X86-NOSSE-NEXT: shrl $2, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %edx, %esi +; X86-NOSSE-NEXT: movl %esi, %edx +; X86-NOSSE-NEXT: shrl $4, %edx +; X86-NOSSE-NEXT: addl %esi, %edx +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: shrl %esi +; X86-NOSSE-NEXT: andl $1431655765, %esi # imm = 0x55555555 +; X86-NOSSE-NEXT: subl %esi, %eax +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: andl $858993459, %esi # imm = 0x33333333 +; X86-NOSSE-NEXT: shrl $2, %eax +; X86-NOSSE-NEXT: andl $858993459, %eax # imm = 0x33333333 +; X86-NOSSE-NEXT: addl %esi, %eax +; X86-NOSSE-NEXT: movl %eax, %esi +; X86-NOSSE-NEXT: shrl $4, %esi +; X86-NOSSE-NEXT: addl %eax, %esi +; X86-NOSSE-NEXT: andl $252645135, %edx # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %edx, %eax # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %eax +; X86-NOSSE-NEXT: andl $252645135, %esi # imm = 0xF0F0F0F +; X86-NOSSE-NEXT: imull $16843009, %esi, %edx # imm = 0x1010101 +; X86-NOSSE-NEXT: shrl $24, %edx +; X86-NOSSE-NEXT: addl %eax, %edx +; X86-NOSSE-NEXT: movl 8(%ebp), %eax +; X86-NOSSE-NEXT: addl %ecx, %edx +; X86-NOSSE-NEXT: xorl %ecx, %ecx +; X86-NOSSE-NEXT: movl %ecx, 12(%eax) +; X86-NOSSE-NEXT: movl %ecx, 8(%eax) +; X86-NOSSE-NEXT: movl %ecx, 4(%eax) +; X86-NOSSE-NEXT: movl %edx, (%eax) +; X86-NOSSE-NEXT: leal -8(%ebp), %esp ; X86-NOSSE-NEXT: popl %esi ; X86-NOSSE-NEXT: popl %edi -; X86-NOSSE-NEXT: popl %ebx +; X86-NOSSE-NEXT: popl %ebp ; X86-NOSSE-NEXT: retl $4 ; ; X64-BASE-LABEL: cnt128_pgso: @@ -1538,13 +1585,17 @@ define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; ; X86-POPCNT-LABEL: cnt128_pgso: ; X86-POPCNT: # %bb.0: +; X86-POPCNT-NEXT: pushl %ebp +; X86-POPCNT-NEXT: movl %esp, %ebp ; X86-POPCNT-NEXT: pushl %esi -; X86-POPCNT-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %edx +; X86-POPCNT-NEXT: andl $-16, %esp +; X86-POPCNT-NEXT: subl $16, %esp +; X86-POPCNT-NEXT: movl 8(%ebp), %eax +; X86-POPCNT-NEXT: popcntl 36(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 32(%ebp), %edx ; X86-POPCNT-NEXT: addl %ecx, %edx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx -; X86-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %esi +; X86-POPCNT-NEXT: popcntl 28(%ebp), %ecx +; X86-POPCNT-NEXT: popcntl 24(%ebp), %esi ; X86-POPCNT-NEXT: addl %ecx, %esi ; X86-POPCNT-NEXT: addl %edx, %esi ; X86-POPCNT-NEXT: xorl %ecx, %ecx @@ -1552,7 +1603,9 @@ define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; X86-POPCNT-NEXT: movl %ecx, 8(%eax) ; X86-POPCNT-NEXT: movl %ecx, 4(%eax) ; X86-POPCNT-NEXT: movl %esi, (%eax) +; X86-POPCNT-NEXT: leal -4(%ebp), %esp ; X86-POPCNT-NEXT: popl %esi +; X86-POPCNT-NEXT: popl %ebp ; X86-POPCNT-NEXT: retl $4 ; ; X64-POPCNT-LABEL: cnt128_pgso: @@ -1599,7 +1652,11 @@ define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; ; X86-SSE2-LABEL: cnt128_pgso: ; X86-SSE2: # %bb.0: -; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: pushl %ebp +; X86-SSE2-NEXT: movl %esp, %ebp +; X86-SSE2-NEXT: andl $-16, %esp +; X86-SSE2-NEXT: subl $16, %esp +; X86-SSE2-NEXT: movl 8(%ebp), %eax ; X86-SSE2-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSE2-NEXT: movdqa %xmm2, %xmm0 ; X86-SSE2-NEXT: psrlw $1, %xmm0 @@ -1642,11 +1699,17 @@ define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; X86-SSE2-NEXT: movl %ecx, 8(%eax) ; X86-SSE2-NEXT: movl %ecx, 4(%eax) ; X86-SSE2-NEXT: movl %edx, (%eax) +; X86-SSE2-NEXT: movl %ebp, %esp +; X86-SSE2-NEXT: popl %ebp ; X86-SSE2-NEXT: retl $4 ; ; X86-SSSE3-LABEL: cnt128_pgso: ; X86-SSSE3: # %bb.0: -; X86-SSSE3-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSSE3-NEXT: pushl %ebp +; X86-SSSE3-NEXT: movl %esp, %ebp +; X86-SSSE3-NEXT: andl $-16, %esp +; X86-SSSE3-NEXT: subl $16, %esp +; X86-SSSE3-NEXT: movl 8(%ebp), %eax ; X86-SSSE3-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; X86-SSSE3-NEXT: movq {{.*#+}} xmm2 = mem[0],zero ; X86-SSSE3-NEXT: movdqa %xmm2, %xmm3 @@ -1679,6 +1742,8 @@ define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { ; X86-SSSE3-NEXT: movl %ecx, 8(%eax) ; X86-SSSE3-NEXT: movl %ecx, 4(%eax) ; X86-SSSE3-NEXT: movl %edx, (%eax) +; X86-SSSE3-NEXT: movl %ebp, %esp +; X86-SSSE3-NEXT: popl %ebp ; X86-SSSE3-NEXT: retl $4 %cnt = tail call i128 @llvm.ctpop.i128(i128 %x) ret i128 %cnt diff --git a/llvm/test/CodeGen/X86/pr154492.ll b/llvm/test/CodeGen/X86/pr154492.ll new file mode 100644 index 0000000000000..1ba17594976e1 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr154492.ll @@ -0,0 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f | FileCheck %s --check-prefix=AVX512F +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512vl | FileCheck %s --check-prefix=AVX512VL + +define <16 x i32> @PR154492() { +; AVX512F-LABEL: PR154492: +; AVX512F: # %bb.0: +; AVX512F-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0 +; AVX512F-NEXT: vmovaps %ymm0, %ymm0 +; AVX512F-NEXT: retq +; +; AVX512VL-LABEL: PR154492: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX512VL-NEXT: vcvttps2udq %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %res = call <16 x i32> @llvm.x86.avx512.mask.cvttps2udq.512(<16 x float> zeroinitializer, <16 x i32> zeroinitializer, i16 255, i32 4) + ret <16 x i32> %res +} diff --git a/llvm/test/CodeGen/X86/pr156256.ll b/llvm/test/CodeGen/X86/pr156256.ll new file mode 100644 index 0000000000000..13caa6fee5878 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr156256.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512dq | FileCheck %s --check-prefix=AVX512 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512dq,+avx512vl | FileCheck %s --check-prefix=AVX512VL + +define <16 x i16> @PR156256(<16 x i32> %a, <16 x i32> %b) { +; AVX512-LABEL: PR156256: +; AVX512: # %bb.0: +; AVX512-NEXT: vpcmpnleud %zmm1, %zmm0, %k0 +; AVX512-NEXT: vpmovm2d %k0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX512-NEXT: retq +; +; AVX512VL-LABEL: PR156256: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: vpcmpnleud %zmm1, %zmm0, %k0 +; AVX512VL-NEXT: vpmovm2d %k0, %zmm0 +; AVX512VL-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512VL-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %icmp = icmp ugt <16 x i32> %a, %b + %sext = sext <16 x i1> %icmp to <16 x i16> + %and = and <16 x i16> %sext, splat (i16 16256) + ret <16 x i16> %and +} diff --git a/llvm/test/CodeGen/X86/pr46004.ll b/llvm/test/CodeGen/X86/pr46004.ll index f7c7da089c365..829d6dfceba3d 100644 --- a/llvm/test/CodeGen/X86/pr46004.ll +++ b/llvm/test/CodeGen/X86/pr46004.ll @@ -6,7 +6,17 @@ define void @fuzz22357(i128 %a0) { ; X86-LABEL: fuzz22357: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp ; X86-NEXT: movb $0, (%eax) +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl ; ; X64-LABEL: fuzz22357: @@ -24,6 +34,15 @@ define void @fuzz22357(i128 %a0) { define void @fuzz22723(i128 %a0) { ; X86-LABEL: fuzz22723: ; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl ; ; X64-LABEL: fuzz22723: diff --git a/llvm/test/CodeGen/X86/scalar-fp-to-i32.ll b/llvm/test/CodeGen/X86/scalar-fp-to-i32.ll index 50a967e1c2a1a..ce9723b3a84bc 100644 --- a/llvm/test/CodeGen/X86/scalar-fp-to-i32.ll +++ b/llvm/test/CodeGen/X86/scalar-fp-to-i32.ll @@ -762,11 +762,15 @@ define i32 @x_to_s32(x86_fp80 %a) nounwind { define i32 @t_to_u32(fp128 %a) nounwind { ; X86-AVX512-WIN-LABEL: t_to_u32: ; X86-AVX512-WIN: # %bb.0: -; X86-AVX512-WIN-NEXT: subl $16, %esp -; X86-AVX512-WIN-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-AVX512-WIN-NEXT: pushl %ebp +; X86-AVX512-WIN-NEXT: movl %esp, %ebp +; X86-AVX512-WIN-NEXT: andl $-16, %esp +; X86-AVX512-WIN-NEXT: subl $32, %esp +; X86-AVX512-WIN-NEXT: vmovups 8(%ebp), %xmm0 ; X86-AVX512-WIN-NEXT: vmovups %xmm0, (%esp) ; X86-AVX512-WIN-NEXT: calll ___fixunstfsi -; X86-AVX512-WIN-NEXT: addl $16, %esp +; X86-AVX512-WIN-NEXT: movl %ebp, %esp +; X86-AVX512-WIN-NEXT: popl %ebp ; X86-AVX512-WIN-NEXT: retl ; ; X86-AVX512-LIN-LABEL: t_to_u32: @@ -797,12 +801,18 @@ define i32 @t_to_u32(fp128 %a) nounwind { ; ; X86-SSE-WIN-LABEL: t_to_u32: ; X86-SSE-WIN: # %bb.0: -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X86-SSE-WIN-NEXT: pushl %ebp +; X86-SSE-WIN-NEXT: movl %esp, %ebp +; X86-SSE-WIN-NEXT: andl $-16, %esp +; X86-SSE-WIN-NEXT: subl $16, %esp +; X86-SSE-WIN-NEXT: pushl 20(%ebp) +; X86-SSE-WIN-NEXT: pushl 16(%ebp) +; X86-SSE-WIN-NEXT: pushl 12(%ebp) +; X86-SSE-WIN-NEXT: pushl 8(%ebp) ; X86-SSE-WIN-NEXT: calll ___fixunstfsi ; X86-SSE-WIN-NEXT: addl $16, %esp +; X86-SSE-WIN-NEXT: movl %ebp, %esp +; X86-SSE-WIN-NEXT: popl %ebp ; X86-SSE-WIN-NEXT: retl ; ; X86-SSE-LIN-LABEL: t_to_u32: @@ -835,12 +845,18 @@ define i32 @t_to_u32(fp128 %a) nounwind { ; ; X87-WIN-LABEL: t_to_u32: ; X87-WIN: # %bb.0: -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X87-WIN-NEXT: pushl %ebp +; X87-WIN-NEXT: movl %esp, %ebp +; X87-WIN-NEXT: andl $-16, %esp +; X87-WIN-NEXT: subl $16, %esp +; X87-WIN-NEXT: pushl 20(%ebp) +; X87-WIN-NEXT: pushl 16(%ebp) +; X87-WIN-NEXT: pushl 12(%ebp) +; X87-WIN-NEXT: pushl 8(%ebp) ; X87-WIN-NEXT: calll ___fixunstfsi ; X87-WIN-NEXT: addl $16, %esp +; X87-WIN-NEXT: movl %ebp, %esp +; X87-WIN-NEXT: popl %ebp ; X87-WIN-NEXT: retl ; ; X87-LIN-LABEL: t_to_u32: @@ -860,11 +876,15 @@ define i32 @t_to_u32(fp128 %a) nounwind { define i32 @t_to_s32(fp128 %a) nounwind { ; X86-AVX512-WIN-LABEL: t_to_s32: ; X86-AVX512-WIN: # %bb.0: -; X86-AVX512-WIN-NEXT: subl $16, %esp -; X86-AVX512-WIN-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-AVX512-WIN-NEXT: pushl %ebp +; X86-AVX512-WIN-NEXT: movl %esp, %ebp +; X86-AVX512-WIN-NEXT: andl $-16, %esp +; X86-AVX512-WIN-NEXT: subl $32, %esp +; X86-AVX512-WIN-NEXT: vmovups 8(%ebp), %xmm0 ; X86-AVX512-WIN-NEXT: vmovups %xmm0, (%esp) ; X86-AVX512-WIN-NEXT: calll ___fixtfsi -; X86-AVX512-WIN-NEXT: addl $16, %esp +; X86-AVX512-WIN-NEXT: movl %ebp, %esp +; X86-AVX512-WIN-NEXT: popl %ebp ; X86-AVX512-WIN-NEXT: retl ; ; X86-AVX512-LIN-LABEL: t_to_s32: @@ -895,12 +915,18 @@ define i32 @t_to_s32(fp128 %a) nounwind { ; ; X86-SSE-WIN-LABEL: t_to_s32: ; X86-SSE-WIN: # %bb.0: -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X86-SSE-WIN-NEXT: pushl %ebp +; X86-SSE-WIN-NEXT: movl %esp, %ebp +; X86-SSE-WIN-NEXT: andl $-16, %esp +; X86-SSE-WIN-NEXT: subl $16, %esp +; X86-SSE-WIN-NEXT: pushl 20(%ebp) +; X86-SSE-WIN-NEXT: pushl 16(%ebp) +; X86-SSE-WIN-NEXT: pushl 12(%ebp) +; X86-SSE-WIN-NEXT: pushl 8(%ebp) ; X86-SSE-WIN-NEXT: calll ___fixtfsi ; X86-SSE-WIN-NEXT: addl $16, %esp +; X86-SSE-WIN-NEXT: movl %ebp, %esp +; X86-SSE-WIN-NEXT: popl %ebp ; X86-SSE-WIN-NEXT: retl ; ; X86-SSE-LIN-LABEL: t_to_s32: @@ -933,12 +959,18 @@ define i32 @t_to_s32(fp128 %a) nounwind { ; ; X87-WIN-LABEL: t_to_s32: ; X87-WIN: # %bb.0: -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X87-WIN-NEXT: pushl %ebp +; X87-WIN-NEXT: movl %esp, %ebp +; X87-WIN-NEXT: andl $-16, %esp +; X87-WIN-NEXT: subl $16, %esp +; X87-WIN-NEXT: pushl 20(%ebp) +; X87-WIN-NEXT: pushl 16(%ebp) +; X87-WIN-NEXT: pushl 12(%ebp) +; X87-WIN-NEXT: pushl 8(%ebp) ; X87-WIN-NEXT: calll ___fixtfsi ; X87-WIN-NEXT: addl $16, %esp +; X87-WIN-NEXT: movl %ebp, %esp +; X87-WIN-NEXT: popl %ebp ; X87-WIN-NEXT: retl ; ; X87-LIN-LABEL: t_to_s32: diff --git a/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll b/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll index f516db8b30ffe..3287869f2c601 100644 --- a/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll +++ b/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll @@ -1417,11 +1417,15 @@ define i64 @x_to_s64(x86_fp80 %a) nounwind { define i64 @t_to_u64(fp128 %a) nounwind { ; X86-AVX512-WIN-LABEL: t_to_u64: ; X86-AVX512-WIN: # %bb.0: -; X86-AVX512-WIN-NEXT: subl $16, %esp -; X86-AVX512-WIN-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-AVX512-WIN-NEXT: pushl %ebp +; X86-AVX512-WIN-NEXT: movl %esp, %ebp +; X86-AVX512-WIN-NEXT: andl $-16, %esp +; X86-AVX512-WIN-NEXT: subl $32, %esp +; X86-AVX512-WIN-NEXT: vmovups 8(%ebp), %xmm0 ; X86-AVX512-WIN-NEXT: vmovups %xmm0, (%esp) ; X86-AVX512-WIN-NEXT: calll ___fixunstfdi -; X86-AVX512-WIN-NEXT: addl $16, %esp +; X86-AVX512-WIN-NEXT: movl %ebp, %esp +; X86-AVX512-WIN-NEXT: popl %ebp ; X86-AVX512-WIN-NEXT: retl ; ; X86-AVX512-LIN-LABEL: t_to_u64: @@ -1452,12 +1456,18 @@ define i64 @t_to_u64(fp128 %a) nounwind { ; ; X86-SSE-WIN-LABEL: t_to_u64: ; X86-SSE-WIN: # %bb.0: -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X86-SSE-WIN-NEXT: pushl %ebp +; X86-SSE-WIN-NEXT: movl %esp, %ebp +; X86-SSE-WIN-NEXT: andl $-16, %esp +; X86-SSE-WIN-NEXT: subl $16, %esp +; X86-SSE-WIN-NEXT: pushl 20(%ebp) +; X86-SSE-WIN-NEXT: pushl 16(%ebp) +; X86-SSE-WIN-NEXT: pushl 12(%ebp) +; X86-SSE-WIN-NEXT: pushl 8(%ebp) ; X86-SSE-WIN-NEXT: calll ___fixunstfdi ; X86-SSE-WIN-NEXT: addl $16, %esp +; X86-SSE-WIN-NEXT: movl %ebp, %esp +; X86-SSE-WIN-NEXT: popl %ebp ; X86-SSE-WIN-NEXT: retl ; ; X86-SSE-LIN-LABEL: t_to_u64: @@ -1490,12 +1500,18 @@ define i64 @t_to_u64(fp128 %a) nounwind { ; ; X87-WIN-LABEL: t_to_u64: ; X87-WIN: # %bb.0: -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X87-WIN-NEXT: pushl %ebp +; X87-WIN-NEXT: movl %esp, %ebp +; X87-WIN-NEXT: andl $-16, %esp +; X87-WIN-NEXT: subl $16, %esp +; X87-WIN-NEXT: pushl 20(%ebp) +; X87-WIN-NEXT: pushl 16(%ebp) +; X87-WIN-NEXT: pushl 12(%ebp) +; X87-WIN-NEXT: pushl 8(%ebp) ; X87-WIN-NEXT: calll ___fixunstfdi ; X87-WIN-NEXT: addl $16, %esp +; X87-WIN-NEXT: movl %ebp, %esp +; X87-WIN-NEXT: popl %ebp ; X87-WIN-NEXT: retl ; ; X87-LIN-LABEL: t_to_u64: @@ -1515,11 +1531,15 @@ define i64 @t_to_u64(fp128 %a) nounwind { define i64 @t_to_s64(fp128 %a) nounwind { ; X86-AVX512-WIN-LABEL: t_to_s64: ; X86-AVX512-WIN: # %bb.0: -; X86-AVX512-WIN-NEXT: subl $16, %esp -; X86-AVX512-WIN-NEXT: vmovups {{[0-9]+}}(%esp), %xmm0 +; X86-AVX512-WIN-NEXT: pushl %ebp +; X86-AVX512-WIN-NEXT: movl %esp, %ebp +; X86-AVX512-WIN-NEXT: andl $-16, %esp +; X86-AVX512-WIN-NEXT: subl $32, %esp +; X86-AVX512-WIN-NEXT: vmovups 8(%ebp), %xmm0 ; X86-AVX512-WIN-NEXT: vmovups %xmm0, (%esp) ; X86-AVX512-WIN-NEXT: calll ___fixtfdi -; X86-AVX512-WIN-NEXT: addl $16, %esp +; X86-AVX512-WIN-NEXT: movl %ebp, %esp +; X86-AVX512-WIN-NEXT: popl %ebp ; X86-AVX512-WIN-NEXT: retl ; ; X86-AVX512-LIN-LABEL: t_to_s64: @@ -1550,12 +1570,18 @@ define i64 @t_to_s64(fp128 %a) nounwind { ; ; X86-SSE-WIN-LABEL: t_to_s64: ; X86-SSE-WIN: # %bb.0: -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X86-SSE-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X86-SSE-WIN-NEXT: pushl %ebp +; X86-SSE-WIN-NEXT: movl %esp, %ebp +; X86-SSE-WIN-NEXT: andl $-16, %esp +; X86-SSE-WIN-NEXT: subl $16, %esp +; X86-SSE-WIN-NEXT: pushl 20(%ebp) +; X86-SSE-WIN-NEXT: pushl 16(%ebp) +; X86-SSE-WIN-NEXT: pushl 12(%ebp) +; X86-SSE-WIN-NEXT: pushl 8(%ebp) ; X86-SSE-WIN-NEXT: calll ___fixtfdi ; X86-SSE-WIN-NEXT: addl $16, %esp +; X86-SSE-WIN-NEXT: movl %ebp, %esp +; X86-SSE-WIN-NEXT: popl %ebp ; X86-SSE-WIN-NEXT: retl ; ; X86-SSE-LIN-LABEL: t_to_s64: @@ -1588,12 +1614,18 @@ define i64 @t_to_s64(fp128 %a) nounwind { ; ; X87-WIN-LABEL: t_to_s64: ; X87-WIN: # %bb.0: -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) -; X87-WIN-NEXT: pushl {{[0-9]+}}(%esp) +; X87-WIN-NEXT: pushl %ebp +; X87-WIN-NEXT: movl %esp, %ebp +; X87-WIN-NEXT: andl $-16, %esp +; X87-WIN-NEXT: subl $16, %esp +; X87-WIN-NEXT: pushl 20(%ebp) +; X87-WIN-NEXT: pushl 16(%ebp) +; X87-WIN-NEXT: pushl 12(%ebp) +; X87-WIN-NEXT: pushl 8(%ebp) ; X87-WIN-NEXT: calll ___fixtfdi ; X87-WIN-NEXT: addl $16, %esp +; X87-WIN-NEXT: movl %ebp, %esp +; X87-WIN-NEXT: popl %ebp ; X87-WIN-NEXT: retl ; ; X87-LIN-LABEL: t_to_s64: diff --git a/llvm/test/CodeGen/X86/scmp.ll b/llvm/test/CodeGen/X86/scmp.ll index 874913629e9e3..8a287229a1cb1 100644 --- a/llvm/test/CodeGen/X86/scmp.ll +++ b/llvm/test/CodeGen/X86/scmp.ll @@ -118,30 +118,33 @@ define i8 @scmp.8.128(i128 %x, i128 %y) nounwind { ; X86-LABEL: scmp.8.128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: cmpl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %ebx, %ebp -; X86-NEXT: sbbl %edx, %ebp -; X86-NEXT: movl %ecx, %ebp -; X86-NEXT: sbbl %eax, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl %esi, %ecx -; X86-NEXT: sbbl %ebp, %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 24(%ebp), %ecx +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %edi +; X86-NEXT: cmpl %ecx, 8(%ebp) +; X86-NEXT: sbbl %eax, %edi +; X86-NEXT: movl 32(%ebp), %edi +; X86-NEXT: movl 16(%ebp), %ebx +; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl 36(%ebp), %ebx +; X86-NEXT: movl 20(%ebp), %edx +; X86-NEXT: movl %edx, %ecx +; X86-NEXT: sbbl %ebx, %ecx ; X86-NEXT: setl %cl -; X86-NEXT: cmpl %edi, {{[0-9]+}}(%esp) -; X86-NEXT: sbbl %ebx, %edx -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: sbbl %esi, %ebp +; X86-NEXT: movl 24(%ebp), %esi +; X86-NEXT: cmpl 8(%ebp), %esi +; X86-NEXT: sbbl 12(%ebp), %eax +; X86-NEXT: sbbl 16(%ebp), %edi +; X86-NEXT: sbbl %edx, %ebx ; X86-NEXT: setl %al ; X86-NEXT: subb %cl, %al +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/sdiv_fix.ll b/llvm/test/CodeGen/X86/sdiv_fix.ll index 4925f8bc6c8b0..392bc83d9d5d8 100644 --- a/llvm/test/CodeGen/X86/sdiv_fix.ll +++ b/llvm/test/CodeGen/X86/sdiv_fix.ll @@ -307,69 +307,70 @@ define i64 @func5(i64 %x, i64 %y) nounwind { ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp -; X86-NEXT: subl $80, %esp +; X86-NEXT: subl $112, %esp ; X86-NEXT: movl 8(%ebp), %ecx -; X86-NEXT: movl 12(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %edi +; X86-NEXT: movl 16(%ebp), %eax ; X86-NEXT: movl 20(%ebp), %edx -; X86-NEXT: movl %edx, %esi +; X86-NEXT: movl %edx, %ebx +; X86-NEXT: sarl $31, %ebx +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, %esi ; X86-NEXT: sarl $31, %esi -; X86-NEXT: movl %eax, %edi -; X86-NEXT: sarl $31, %edi -; X86-NEXT: movl %edi, %ebx -; X86-NEXT: shldl $31, %eax, %ebx -; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: shldl $31, %ecx, %eax -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: shldl $31, %edi, %esi +; X86-NEXT: shldl $31, %ecx, %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) ; X86-NEXT: shll $31, %ecx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %edx -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %ecx -; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %eax +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: subl $1, %eax -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: sbbl $0, %ebx -; X86-NEXT: testl %esi, %esi -; X86-NEXT: sets %al -; X86-NEXT: testl %edi, %edi -; X86-NEXT: sets %cl -; X86-NEXT: xorb %al, %cl -; X86-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 20(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl 20(%ebp) -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl %edi -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: subl $1, %esi +; X86-NEXT: sbbl $0, %edi +; X86-NEXT: testl %ebx, %ebx +; X86-NEXT: sets %al +; X86-NEXT: testl %ecx, %ecx +; X86-NEXT: sets %bl +; X86-NEXT: xorb %al, %bl ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: setne %al -; X86-NEXT: testb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Reload -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload -; X86-NEXT: movl %ebx, %edx +; X86-NEXT: testb %bl, %al +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload +; X86-NEXT: movl %esi, %eax +; X86-NEXT: movl %edi, %edx ; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi diff --git a/llvm/test/CodeGen/X86/sdiv_fix_sat.ll b/llvm/test/CodeGen/X86/sdiv_fix_sat.ll index e7727a0ab6178..7df490f984928 100644 --- a/llvm/test/CodeGen/X86/sdiv_fix_sat.ll +++ b/llvm/test/CodeGen/X86/sdiv_fix_sat.ll @@ -370,67 +370,68 @@ define i64 @func5(i64 %x, i64 %y) nounwind { ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp -; X86-NEXT: subl $96, %esp -; X86-NEXT: movl 8(%ebp), %ecx -; X86-NEXT: movl 12(%ebp), %eax -; X86-NEXT: movl 20(%ebp), %esi -; X86-NEXT: movl %esi, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: movl %eax, %edx -; X86-NEXT: sarl $31, %edx -; X86-NEXT: movl %edx, %edi -; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: shldl $31, %eax, %edi -; X86-NEXT: shldl $31, %ecx, %eax +; X86-NEXT: subl $128, %esp +; X86-NEXT: movl 8(%ebp), %esi +; X86-NEXT: movl 12(%ebp), %edi +; X86-NEXT: movl 16(%ebp), %ecx +; X86-NEXT: movl 20(%ebp), %edx +; X86-NEXT: movl %edx, %eax +; X86-NEXT: sarl $31, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: shll $31, %ecx -; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %esi -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %ecx +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, %ebx +; X86-NEXT: sarl $31, %ebx +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: shldl $31, %edi, %ebx +; X86-NEXT: shldl $31, %esi, %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: shll $31, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 20(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl 16(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: subl $1, %esi -; X86-NEXT: sbbl $0, %ecx -; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: subl $1, %edi ; X86-NEXT: sbbl $0, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: sbbl $0, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: testl %ebx, %ebx -; X86-NEXT: sets %al -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, %ebx +; X86-NEXT: sbbl $0, %ebx ; X86-NEXT: testl %ecx, %ecx -; X86-NEXT: sets %dl -; X86-NEXT: xorb %al, %dl -; X86-NEXT: movb %dl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl 20(%ebp) -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %edi -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl %eax +; X86-NEXT: sets %al +; X86-NEXT: testl %edx, %edx +; X86-NEXT: sets %cl +; X86-NEXT: xorb %al, %cl +; X86-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx @@ -438,41 +439,38 @@ define i64 @func5(i64 %x, i64 %y) nounwind { ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: setne %al ; X86-NEXT: testb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Reload -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload +; X86-NEXT: cmovel %esi, %ebx ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload ; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Folded Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload -; X86-NEXT: cmpl $-1, %esi -; X86-NEXT: movl %eax, %ecx +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload +; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload +; X86-NEXT: cmpl $-1, %edi ; X86-NEXT: sbbl $2147483647, %ecx # imm = 0x7FFFFFFF -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: movl %edx, %ebx +; X86-NEXT: movl %eax, %ecx ; X86-NEXT: sbbl $0, %ecx -; X86-NEXT: movl %edi, %ecx +; X86-NEXT: movl %ebx, %ecx ; X86-NEXT: sbbl $0, %ecx ; X86-NEXT: movl $2147483647, %edx # imm = 0x7FFFFFFF -; X86-NEXT: cmovll %eax, %edx +; X86-NEXT: cmovll {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload ; X86-NEXT: movl $0, %ecx -; X86-NEXT: cmovgel %ecx, %edi -; X86-NEXT: movl %edi, %eax ; X86-NEXT: cmovgel %ecx, %ebx +; X86-NEXT: cmovgel %ecx, %eax ; X86-NEXT: movl $-1, %ecx -; X86-NEXT: cmovgel %ecx, %esi -; X86-NEXT: movl %esi, %edi -; X86-NEXT: negl %edi -; X86-NEXT: movl $-2147483648, %edi # imm = 0x80000000 -; X86-NEXT: sbbl %edx, %edi -; X86-NEXT: movl $-1, %edi -; X86-NEXT: sbbl %ebx, %edi -; X86-NEXT: sbbl %eax, %ecx +; X86-NEXT: cmovgel %ecx, %edi +; X86-NEXT: movl %edi, %esi +; X86-NEXT: negl %esi +; X86-NEXT: movl $-2147483648, %esi # imm = 0x80000000 +; X86-NEXT: sbbl %edx, %esi +; X86-NEXT: movl $-1, %esi +; X86-NEXT: sbbl %eax, %esi +; X86-NEXT: sbbl %ebx, %ecx ; X86-NEXT: movl $0, %eax -; X86-NEXT: cmovgel %eax, %esi +; X86-NEXT: cmovgel %eax, %edi ; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 ; X86-NEXT: cmovgel %eax, %edx -; X86-NEXT: movl %esi, %eax +; X86-NEXT: movl %edi, %eax ; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi @@ -805,137 +803,155 @@ define <4 x i32> @vec(<4 x i32> %x, <4 x i32> %y) nounwind { ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp -; X86-NEXT: subl $208, %esp -; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: subl $240, %esp +; X86-NEXT: movl 12(%ebp), %esi +; X86-NEXT: movl 20(%ebp), %edi ; X86-NEXT: movl 16(%ebp), %ebx -; X86-NEXT: movl 32(%ebp), %eax -; X86-NEXT: movl %eax, %edi -; X86-NEXT: movl %eax, %ecx -; X86-NEXT: sarl $31, %edi -; X86-NEXT: movl %ebx, %edx -; X86-NEXT: sarl $31, %edx -; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl 32(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) ; X86-NEXT: leal (%ebx,%ebx), %eax ; X86-NEXT: shrl $31, %ebx ; X86-NEXT: shldl $31, %eax, %ebx -; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp -; X86-NEXT: sarl $31, %esi -; X86-NEXT: movl 20(%ebp), %ecx +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 36(%ebp), %ecx ; X86-NEXT: movl %ecx, %eax ; X86-NEXT: sarl $31, %eax -; X86-NEXT: leal (%ecx,%ecx), %edx -; X86-NEXT: shrl $31, %ecx -; X86-NEXT: shldl $31, %edx, %ecx -; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: leal {{[0-9]+}}(%esp), %edx -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl 36(%ebp) ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %edx +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: leal (%edi,%edi), %eax +; X86-NEXT: shrl $31, %edi +; X86-NEXT: shldl $31, %eax, %edi +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl 32(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl 32(%ebp) -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl 36(%ebp) -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp -; X86-NEXT: movl 28(%ebp), %edx -; X86-NEXT: movl %edx, %ebx -; X86-NEXT: sarl $31, %ebx -; X86-NEXT: movl 12(%ebp), %ecx -; X86-NEXT: movl %ecx, %edi +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl %eax, %edi ; X86-NEXT: sarl $31, %edi -; X86-NEXT: leal (%ecx,%ecx), %eax -; X86-NEXT: shrl $31, %ecx -; X86-NEXT: shldl $31, %eax, %ecx -; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %esi, %ebx +; X86-NEXT: sarl $31, %ebx +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: leal (%esi,%esi), %eax +; X86-NEXT: shrl $31, %esi +; X86-NEXT: shldl $31, %eax, %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp -; X86-NEXT: movl 40(%ebp), %esi -; X86-NEXT: sarl $31, %esi -; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: sarl $31, %eax +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) ; X86-NEXT: movl 24(%ebp), %ecx ; X86-NEXT: movl %ecx, %eax ; X86-NEXT: sarl $31, %eax -; X86-NEXT: leal (%ecx,%ecx), %edx +; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: leal (%ecx,%ecx), %eax ; X86-NEXT: shrl $31, %ecx -; X86-NEXT: shldl $31, %edx, %ecx +; X86-NEXT: shldl $31, %eax, %ecx ; X86-NEXT: movl %ecx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: leal {{[0-9]+}}(%esp), %edx -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl %esi -; X86-NEXT: pushl 40(%ebp) -; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %edx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edi, {{[0-9]+}}(%esp) +; X86-NEXT: movl 28(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) +; X86-NEXT: movl %ebx, {{[0-9]+}}(%esp) ; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl %ebx -; X86-NEXT: pushl 28(%ebp) -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %edi -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __divti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl 40(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: subl $1, %eax @@ -949,18 +965,18 @@ define <4 x i32> @vec(<4 x i32> %x, <4 x i32> %y) nounwind { ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl %edx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: sbbl $0, %edx +; X86-NEXT: testl %edi, %edi +; X86-NEXT: sets {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Spill ; X86-NEXT: testl %ebx, %ebx ; X86-NEXT: sets %bl -; X86-NEXT: testl %edi, %edi -; X86-NEXT: sets %bh -; X86-NEXT: xorb %bl, %bh +; X86-NEXT: xorb {{[-0-9]+}}(%e{{[sb]}}p), %bl # 1-byte Folded Reload ; X86-NEXT: movl {{[0-9]+}}(%esp), %edi ; X86-NEXT: orl {{[0-9]+}}(%esp), %edi ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi ; X86-NEXT: orl {{[0-9]+}}(%esp), %esi ; X86-NEXT: orl %edi, %esi -; X86-NEXT: setne %bl -; X86-NEXT: testb %bh, %bl +; X86-NEXT: setne %bh +; X86-NEXT: testb %bl, %bh ; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Folded Reload ; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Reload @@ -1107,36 +1123,24 @@ define <4 x i32> @vec(<4 x i32> %x, <4 x i32> %y) nounwind { ; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx ; X86-NEXT: movl %ebx, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: subl $1, %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: sbbl $0, %edi +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: sbbl $0, %esi ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill ; X86-NEXT: sbbl $0, %eax ; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl %esi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill -; X86-NEXT: sbbl $0, %esi -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload -; X86-NEXT: testl %ecx, %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill +; X86-NEXT: sbbl $0, %edi +; X86-NEXT: cmpl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload ; X86-NEXT: sets %al -; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %edx # 4-byte Reload -; X86-NEXT: testl %edx, %edx -; X86-NEXT: sets %ah -; X86-NEXT: xorb %al, %ah -; X86-NEXT: movb %ah, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill -; X86-NEXT: leal {{[0-9]+}}(%esp), %eax -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl 40(%ebp) -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %edx -; X86-NEXT: pushl {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %eax +; X86-NEXT: cmpl $0, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Folded Reload +; X86-NEXT: sets %cl +; X86-NEXT: xorb %al, %cl +; X86-NEXT: movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill ; X86-NEXT: calll __modti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx @@ -1144,38 +1148,38 @@ define <4 x i32> @vec(<4 x i32> %x, <4 x i32> %y) nounwind { ; X86-NEXT: orl %eax, %ecx ; X86-NEXT: setne %al ; X86-NEXT: testb %al, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload ; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Folded Reload -; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %edi # 4-byte Folded Reload +; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Folded Reload ; X86-NEXT: cmovel {{[-0-9]+}}(%e{{[sb]}}p), %ebx # 4-byte Folded Reload ; X86-NEXT: cmpl $-1, %ebx -; X86-NEXT: movl %edi, %eax +; X86-NEXT: movl %esi, %eax ; X86-NEXT: sbbl $0, %eax ; X86-NEXT: movl %ecx, %eax ; X86-NEXT: sbbl $0, %eax -; X86-NEXT: movl %esi, %eax +; X86-NEXT: movl %edi, %eax ; X86-NEXT: sbbl $0, %eax ; X86-NEXT: movl $0, %eax -; X86-NEXT: cmovgel %eax, %esi -; X86-NEXT: cmovgel %eax, %ecx ; X86-NEXT: cmovgel %eax, %edi +; X86-NEXT: cmovgel %eax, %ecx +; X86-NEXT: cmovgel %eax, %esi ; X86-NEXT: movl $-1, %edx ; X86-NEXT: cmovgel %edx, %ebx ; X86-NEXT: movl %ebx, %eax ; X86-NEXT: negl %eax ; X86-NEXT: movl $-1, %eax -; X86-NEXT: sbbl %edi, %eax +; X86-NEXT: sbbl %esi, %eax ; X86-NEXT: movl $-1, %eax ; X86-NEXT: sbbl %ecx, %eax ; X86-NEXT: movl $-1, %eax -; X86-NEXT: sbbl %esi, %eax +; X86-NEXT: sbbl %edi, %eax ; X86-NEXT: movl $0, %eax ; X86-NEXT: cmovgel %eax, %ebx -; X86-NEXT: cmovgel %edx, %edi -; X86-NEXT: shldl $31, %ebx, %edi +; X86-NEXT: cmovgel %edx, %esi +; X86-NEXT: shldl $31, %ebx, %esi ; X86-NEXT: movl 8(%ebp), %eax -; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: movl %esi, 12(%eax) ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload ; X86-NEXT: movl %ecx, 8(%eax) ; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload diff --git a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll index d2b292f1a7996..2ac2be5545dfd 100644 --- a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll +++ b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll @@ -119,8 +119,8 @@ define void @failing(ptr %0, ptr %1) nounwind { ; CHECK-AVX2-NEXT: .LBB0_2: # %vector.body ; CHECK-AVX2-NEXT: # Parent Loop BB0_1 Depth=1 ; CHECK-AVX2-NEXT: # => This Inner Loop Header: Depth=2 -; CHECK-AVX2-NEXT: vmovdqu 1024(%rdx,%rsi), %ymm5 -; CHECK-AVX2-NEXT: vextracti128 $1, %ymm5, %xmm6 +; CHECK-AVX2-NEXT: vmovdqu 1024(%rdx,%rsi), %xmm5 +; CHECK-AVX2-NEXT: vmovdqu 1040(%rdx,%rsi), %xmm6 ; CHECK-AVX2-NEXT: vpextrq $1, %xmm5, %rdi ; CHECK-AVX2-NEXT: vpextrq $1, %xmm6, %r8 ; CHECK-AVX2-NEXT: vmovq %xmm5, %r9 diff --git a/llvm/test/CodeGen/X86/shift-combine.ll b/llvm/test/CodeGen/X86/shift-combine.ll index 76cb4e87bae18..dfeef48897e06 100644 --- a/llvm/test/CodeGen/X86/shift-combine.ll +++ b/llvm/test/CodeGen/X86/shift-combine.ll @@ -792,14 +792,24 @@ define <4 x i32> @or_tree_with_mismatching_shifts_vec_i32(<4 x i32> %a, <4 x i32 define void @combineShiftOfShiftedLogic(i128 %a1, i32 %a2, ptr %p) { ; X86-LABEL: combineShiftOfShiftedLogic: ; X86: # %bb.0: -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 24(%ebp), %eax +; X86-NEXT: movl 28(%ebp), %ecx ; X86-NEXT: movl %eax, 20(%ecx) ; X86-NEXT: movl $0, 16(%ecx) ; X86-NEXT: movl $0, 12(%ecx) ; X86-NEXT: movl $0, 8(%ecx) ; X86-NEXT: movl $0, 4(%ecx) ; X86-NEXT: movl $0, (%ecx) +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 ; X86-NEXT: retl ; ; X64-LABEL: combineShiftOfShiftedLogic: diff --git a/llvm/test/CodeGen/X86/shift-i128.ll b/llvm/test/CodeGen/X86/shift-i128.ll index 767bd772ab7a3..9323cd5b1917f 100644 --- a/llvm/test/CodeGen/X86/shift-i128.ll +++ b/llvm/test/CodeGen/X86/shift-i128.ll @@ -212,9 +212,18 @@ entry: } define void @test_lshr_i128_outofrange(i128 %x, ptr nocapture %r) nounwind { -; ALL-LABEL: test_lshr_i128_outofrange: -; ALL: # %bb.0: # %entry -; ALL-NEXT: ret{{[l|q]}} +; i686-LABEL: test_lshr_i128_outofrange: +; i686: # %bb.0: # %entry +; i686-NEXT: pushl %ebp +; i686-NEXT: movl %esp, %ebp +; i686-NEXT: andl $-16, %esp +; i686-NEXT: movl %ebp, %esp +; i686-NEXT: popl %ebp +; i686-NEXT: retl +; +; x86_64-LABEL: test_lshr_i128_outofrange: +; x86_64: # %bb.0: # %entry +; x86_64-NEXT: retq entry: %0 = lshr i128 %x, -1 store i128 %0, ptr %r, align 16 @@ -222,9 +231,18 @@ entry: } define void @test_ashr_i128_outofrange(i128 %x, ptr nocapture %r) nounwind { -; ALL-LABEL: test_ashr_i128_outofrange: -; ALL: # %bb.0: # %entry -; ALL-NEXT: ret{{[l|q]}} +; i686-LABEL: test_ashr_i128_outofrange: +; i686: # %bb.0: # %entry +; i686-NEXT: pushl %ebp +; i686-NEXT: movl %esp, %ebp +; i686-NEXT: andl $-16, %esp +; i686-NEXT: movl %ebp, %esp +; i686-NEXT: popl %ebp +; i686-NEXT: retl +; +; x86_64-LABEL: test_ashr_i128_outofrange: +; x86_64: # %bb.0: # %entry +; x86_64-NEXT: retq entry: %0 = ashr i128 %x, -1 store i128 %0, ptr %r, align 16 @@ -232,9 +250,18 @@ entry: } define void @test_shl_i128_outofrange(i128 %x, ptr nocapture %r) nounwind { -; ALL-LABEL: test_shl_i128_outofrange: -; ALL: # %bb.0: # %entry -; ALL-NEXT: ret{{[l|q]}} +; i686-LABEL: test_shl_i128_outofrange: +; i686: # %bb.0: # %entry +; i686-NEXT: pushl %ebp +; i686-NEXT: movl %esp, %ebp +; i686-NEXT: andl $-16, %esp +; i686-NEXT: movl %ebp, %esp +; i686-NEXT: popl %ebp +; i686-NEXT: retl +; +; x86_64-LABEL: test_shl_i128_outofrange: +; x86_64: # %bb.0: # %entry +; x86_64-NEXT: retq entry: %0 = shl i128 %x, -1 store i128 %0, ptr %r, align 16 @@ -874,26 +901,31 @@ define <2 x i256> @shl_zext_lshr_outofrange(<2 x i128> %a0) { define i128 @lshr_shl_mask(i128 %a0) { ; i686-LABEL: lshr_shl_mask: ; i686: # %bb.0: -; i686-NEXT: pushl %edi +; i686-NEXT: pushl %ebp ; i686-NEXT: .cfi_def_cfa_offset 8 +; i686-NEXT: .cfi_offset %ebp, -8 +; i686-NEXT: movl %esp, %ebp +; i686-NEXT: .cfi_def_cfa_register %ebp +; i686-NEXT: pushl %edi ; i686-NEXT: pushl %esi -; i686-NEXT: .cfi_def_cfa_offset 12 -; i686-NEXT: .cfi_offset %esi, -12 -; i686-NEXT: .cfi_offset %edi, -8 -; i686-NEXT: movl {{[0-9]+}}(%esp), %eax -; i686-NEXT: movl {{[0-9]+}}(%esp), %ecx -; i686-NEXT: movl {{[0-9]+}}(%esp), %edx -; i686-NEXT: movl {{[0-9]+}}(%esp), %esi +; i686-NEXT: andl $-16, %esp +; i686-NEXT: .cfi_offset %esi, -16 +; i686-NEXT: .cfi_offset %edi, -12 +; i686-NEXT: movl 8(%ebp), %eax +; i686-NEXT: movl 24(%ebp), %ecx +; i686-NEXT: movl 28(%ebp), %edx +; i686-NEXT: movl 32(%ebp), %esi ; i686-NEXT: movl $2147483647, %edi # imm = 0x7FFFFFFF -; i686-NEXT: andl {{[0-9]+}}(%esp), %edi +; i686-NEXT: andl 36(%ebp), %edi ; i686-NEXT: movl %edi, 12(%eax) ; i686-NEXT: movl %esi, 8(%eax) ; i686-NEXT: movl %edx, 4(%eax) ; i686-NEXT: movl %ecx, (%eax) +; i686-NEXT: leal -8(%ebp), %esp ; i686-NEXT: popl %esi -; i686-NEXT: .cfi_def_cfa_offset 8 ; i686-NEXT: popl %edi -; i686-NEXT: .cfi_def_cfa_offset 4 +; i686-NEXT: popl %ebp +; i686-NEXT: .cfi_def_cfa %esp, 4 ; i686-NEXT: retl $4 ; ; x86_64-LABEL: lshr_shl_mask: diff --git a/llvm/test/CodeGen/X86/smax.ll b/llvm/test/CodeGen/X86/smax.ll index 86891e964d96d..509d4443e930a 100644 --- a/llvm/test/CodeGen/X86/smax.ll +++ b/llvm/test/CodeGen/X86/smax.ll @@ -151,31 +151,34 @@ define i128 @test_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: test_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmpl %ebx, %edx -; X86-NEXT: movl %esi, %ebp -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl %edi, %ebp -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ebx +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: cmpl 24(%ebp), %ebx +; X86-NEXT: movl %edi, %esi +; X86-NEXT: sbbl 28(%ebp), %esi +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl %edx, %esi +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl 52(%ebp), %ecx ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: sbbl %ebp, %eax -; X86-NEXT: cmovll %ebx, %edx -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovll %ebp, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sbbl %esi, %eax +; X86-NEXT: cmovll 24(%ebp), %ebx +; X86-NEXT: cmovll 28(%ebp), %edi +; X86-NEXT: cmovll 32(%ebp), %edx +; X86-NEXT: cmovll %esi, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %ecx, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %ebx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -717,29 +720,32 @@ define i128 @test_signbits_i128(i128 %a, i128 %b) nounwind { ; ; X86-LABEL: test_signbits_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: shrdl $28, %edi, %ecx -; X86-NEXT: sarl $28, %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %ecx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: shrdl $28, %edx, %ecx +; X86-NEXT: sarl $28, %edx ; X86-NEXT: cmpl %esi, %ecx -; X86-NEXT: movl %edi, %ebx -; X86-NEXT: sbbl %edx, %ebx +; X86-NEXT: movl %edx, %edi +; X86-NEXT: sbbl %eax, %edi ; X86-NEXT: cmovll %esi, %ecx -; X86-NEXT: cmovll %edx, %edi -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: sarl $31, %edi +; X86-NEXT: cmovll %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: sarl $31, %edx +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %ax = ashr i128 %a, 64 %bx = ashr i128 %b, 92 diff --git a/llvm/test/CodeGen/X86/smin.ll b/llvm/test/CodeGen/X86/smin.ll index 8907f6c4cd598..5e9fe27b41d2c 100644 --- a/llvm/test/CodeGen/X86/smin.ll +++ b/llvm/test/CodeGen/X86/smin.ll @@ -151,32 +151,34 @@ define i128 @test_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: test_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: cmpl %edx, %ebx -; X86-NEXT: sbbl %esi, %ebp -; X86-NEXT: movl %eax, %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: cmpl %ecx, 24(%ebp) +; X86-NEXT: sbbl %edx, %esi +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: sbbl %esi, %ebx +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %edi ; X86-NEXT: movl %edi, %eax -; X86-NEXT: sbbl %ebp, %eax -; X86-NEXT: cmovll %ebx, %edx -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovll {{[0-9]+}}(%esp), %ecx -; X86-NEXT: cmovll %edi, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %ebp, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: cmovll 24(%ebp), %ecx +; X86-NEXT: cmovll 28(%ebp), %edx +; X86-NEXT: cmovll 32(%ebp), %esi +; X86-NEXT: cmovll %edi, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -718,29 +720,32 @@ define i128 @test_signbits_i128(i128 %a, i128 %b) nounwind { ; ; X86-LABEL: test_signbits_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: shrdl $28, %edi, %ecx -; X86-NEXT: sarl $28, %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %ecx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: shrdl $28, %edx, %ecx +; X86-NEXT: sarl $28, %edx ; X86-NEXT: cmpl %ecx, %esi -; X86-NEXT: movl %edx, %ebx -; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl %eax, %edi +; X86-NEXT: sbbl %edx, %edi ; X86-NEXT: cmovll %esi, %ecx -; X86-NEXT: cmovll %edx, %edi -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: sarl $31, %edi +; X86-NEXT: cmovll %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: sarl $31, %edx +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %ax = ashr i128 %a, 64 %bx = ashr i128 %b, 92 diff --git a/llvm/test/CodeGen/X86/symbol-name.ll b/llvm/test/CodeGen/X86/symbol-name.ll new file mode 100644 index 0000000000000..dd9be14fb053e --- /dev/null +++ b/llvm/test/CodeGen/X86/symbol-name.ll @@ -0,0 +1,5 @@ +; RUN: llc < %s -mtriple=x86_64 -relocation-model=pic | FileCheck %s + +; CHECK: .globl "\\\"" +; CHECK-NEXT: "\\\"": +@"\\\22" = constant i8 0 diff --git a/llvm/test/CodeGen/X86/ucmp.ll b/llvm/test/CodeGen/X86/ucmp.ll index 6a52acfe2fb30..7f17299b39e33 100644 --- a/llvm/test/CodeGen/X86/ucmp.ll +++ b/llvm/test/CodeGen/X86/ucmp.ll @@ -107,29 +107,33 @@ define i8 @ucmp.8.128(i128 %x, i128 %y) nounwind { ; X86-LABEL: ucmp.8.128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: cmpl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl %ebp, %eax -; X86-NEXT: sbbl %esi, %eax +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl 12(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %ecx +; X86-NEXT: cmpl %eax, 24(%ebp) ; X86-NEXT: movl %ecx, %eax ; X86-NEXT: sbbl %edx, %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %edi, %eax +; X86-NEXT: movl 16(%ebp), %ebx +; X86-NEXT: movl 32(%ebp), %eax +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: movl 20(%ebp), %ecx +; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl %esi, %eax ; X86-NEXT: sbbl %ecx, %eax ; X86-NEXT: setb %al -; X86-NEXT: cmpl %ebx, {{[0-9]+}}(%esp) -; X86-NEXT: sbbl %ebp, %esi -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %edx -; X86-NEXT: sbbl %edi, %ecx +; X86-NEXT: movl 8(%ebp), %edi +; X86-NEXT: cmpl 24(%ebp), %edi +; X86-NEXT: sbbl 28(%ebp), %edx +; X86-NEXT: sbbl 32(%ebp), %ebx +; X86-NEXT: sbbl %esi, %ecx ; X86-NEXT: sbbb $0, %al +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx diff --git a/llvm/test/CodeGen/X86/udiv_fix.ll b/llvm/test/CodeGen/X86/udiv_fix.ll index 5b1e0545502b8..82dfeeee13293 100644 --- a/llvm/test/CodeGen/X86/udiv_fix.ll +++ b/llvm/test/CodeGen/X86/udiv_fix.ll @@ -153,26 +153,28 @@ define i64 @func5(i64 %x, i64 %y) nounwind { ; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp -; X86-NEXT: subl $32, %esp +; X86-NEXT: subl $80, %esp ; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: movl 16(%ebp), %edx +; X86-NEXT: movl 20(%ebp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) ; X86-NEXT: movl %ecx, %edx ; X86-NEXT: shrl %edx +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) ; X86-NEXT: shldl $31, %eax, %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) ; X86-NEXT: shll $31, %eax -; X86-NEXT: movl %esp, %esi -; X86-NEXT: pushl $0 -; X86-NEXT: pushl $0 -; X86-NEXT: pushl 20(%ebp) -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %esi +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __udivti3 -; X86-NEXT: addl $32, %esp -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: subl $4, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: leal -4(%ebp), %esp ; X86-NEXT: popl %esi diff --git a/llvm/test/CodeGen/X86/udiv_fix_sat.ll b/llvm/test/CodeGen/X86/udiv_fix_sat.ll index 30a7f80b2315d..3da5973f9f903 100644 --- a/llvm/test/CodeGen/X86/udiv_fix_sat.ll +++ b/llvm/test/CodeGen/X86/udiv_fix_sat.ll @@ -194,32 +194,34 @@ define i64 @func5(i64 %x, i64 %y) nounwind { ; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %esi ; X86-NEXT: andl $-16, %esp -; X86-NEXT: subl $32, %esp +; X86-NEXT: subl $80, %esp ; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl 12(%ebp), %ecx +; X86-NEXT: movl 16(%ebp), %edx +; X86-NEXT: movl 20(%ebp), %esi +; X86-NEXT: movl %esi, {{[0-9]+}}(%esp) +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) ; X86-NEXT: movl %ecx, %edx ; X86-NEXT: shrl %edx +; X86-NEXT: movl %edx, {{[0-9]+}}(%esp) ; X86-NEXT: shldl $31, %eax, %ecx +; X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) ; X86-NEXT: shll $31, %eax -; X86-NEXT: movl %esp, %esi -; X86-NEXT: pushl $0 -; X86-NEXT: pushl $0 -; X86-NEXT: pushl 20(%ebp) -; X86-NEXT: pushl 16(%ebp) -; X86-NEXT: pushl $0 -; X86-NEXT: pushl %edx -; X86-NEXT: pushl %ecx -; X86-NEXT: pushl %eax -; X86-NEXT: pushl %esi +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) ; X86-NEXT: calll __udivti3 -; X86-NEXT: addl $32, %esp +; X86-NEXT: subl $4, %esp ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: orl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl $-1, %eax ; X86-NEXT: movl $-1, %edx ; X86-NEXT: jne .LBB4_2 ; X86-NEXT: # %bb.1: -; X86-NEXT: movl (%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: .LBB4_2: ; X86-NEXT: leal -4(%ebp), %esp diff --git a/llvm/test/CodeGen/X86/umax.ll b/llvm/test/CodeGen/X86/umax.ll index f589d4a7b04a9..7ef859978cdbf 100644 --- a/llvm/test/CodeGen/X86/umax.ll +++ b/llvm/test/CodeGen/X86/umax.ll @@ -232,31 +232,34 @@ define i128 @test_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: test_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmpl %ebx, %edx -; X86-NEXT: movl %esi, %ebp -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl %edi, %ebp -; X86-NEXT: sbbl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ebx +; X86-NEXT: movl 44(%ebp), %edi +; X86-NEXT: cmpl 24(%ebp), %ebx +; X86-NEXT: movl %edi, %esi +; X86-NEXT: sbbl 28(%ebp), %esi +; X86-NEXT: movl 48(%ebp), %edx +; X86-NEXT: movl %edx, %esi +; X86-NEXT: sbbl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %esi +; X86-NEXT: movl 52(%ebp), %ecx ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: sbbl %ebp, %eax -; X86-NEXT: cmovbl %ebx, %edx -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %edi -; X86-NEXT: cmovbl %ebp, %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sbbl %esi, %eax +; X86-NEXT: cmovbl 24(%ebp), %ebx +; X86-NEXT: cmovbl 28(%ebp), %edi +; X86-NEXT: cmovbl 32(%ebp), %edx +; X86-NEXT: cmovbl %esi, %ecx +; X86-NEXT: movl 8(%ebp), %eax ; X86-NEXT: movl %ecx, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %ebx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -282,37 +285,40 @@ define i128 @test_i128_1(i128 %a) nounwind { ; X86-LABEL: test_i128_1: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 32(%ebp), %edx +; X86-NEXT: movl 24(%ebp), %eax ; X86-NEXT: cmpl $1, %eax -; X86-NEXT: movl %eax, %ebx -; X86-NEXT: adcl $0, %ebx -; X86-NEXT: testl %edx, %edx -; X86-NEXT: movl $1, %edi -; X86-NEXT: cmovnel %eax, %edi -; X86-NEXT: cmovel %ebx, %edi -; X86-NEXT: xorl %ebx, %ebx -; X86-NEXT: movl %ecx, %ebp -; X86-NEXT: negl %ebp -; X86-NEXT: movl $0, %ebp -; X86-NEXT: sbbl %esi, %ebp -; X86-NEXT: movl $1, %ebp -; X86-NEXT: cmovbl %eax, %ebp -; X86-NEXT: movl %ecx, %eax -; X86-NEXT: cmovbl %edx, %ebx -; X86-NEXT: orl %esi, %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %esi, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: cmovel %edi, %ebp -; X86-NEXT: cmovel %edx, %ebx -; X86-NEXT: movl %ebx, 4(%eax) -; X86-NEXT: movl %ebp, (%eax) +; X86-NEXT: movl %eax, %ecx +; X86-NEXT: adcl $0, %ecx +; X86-NEXT: cmpl $0, 28(%ebp) +; X86-NEXT: movl $1, %esi +; X86-NEXT: cmovnel %eax, %esi +; X86-NEXT: cmovel %ecx, %esi +; X86-NEXT: xorl %edi, %edi +; X86-NEXT: movl %edx, %ecx +; X86-NEXT: negl %ecx +; X86-NEXT: movl 36(%ebp), %ecx +; X86-NEXT: movl $0, %ebx +; X86-NEXT: sbbl %ecx, %ebx +; X86-NEXT: movl $1, %ebx +; X86-NEXT: cmovbl %eax, %ebx +; X86-NEXT: cmovbl 28(%ebp), %edi +; X86-NEXT: movl %edx, %eax +; X86-NEXT: orl %ecx, %eax +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: cmovel %esi, %ebx +; X86-NEXT: cmovel 28(%ebp), %edi +; X86-NEXT: movl %edi, 4(%eax) +; X86-NEXT: movl %ebx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -1312,29 +1318,32 @@ define i128 @test_signbits_i128(i128 %a, i128 %b) nounwind { ; ; X86-LABEL: test_signbits_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: shrdl $28, %edi, %ecx -; X86-NEXT: sarl $28, %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %ecx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: shrdl $28, %edx, %ecx +; X86-NEXT: sarl $28, %edx ; X86-NEXT: cmpl %esi, %ecx -; X86-NEXT: movl %edi, %ebx -; X86-NEXT: sbbl %edx, %ebx +; X86-NEXT: movl %edx, %edi +; X86-NEXT: sbbl %eax, %edi ; X86-NEXT: cmovbl %esi, %ecx -; X86-NEXT: cmovbl %edx, %edi -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: sarl $31, %edi +; X86-NEXT: cmovbl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: sarl $31, %edx +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %ax = ashr i128 %a, 64 %bx = ashr i128 %b, 92 diff --git a/llvm/test/CodeGen/X86/umin.ll b/llvm/test/CodeGen/X86/umin.ll index 7a5cdbb9ce758..c927abf3a4263 100644 --- a/llvm/test/CodeGen/X86/umin.ll +++ b/llvm/test/CodeGen/X86/umin.ll @@ -147,32 +147,34 @@ define i128 @test_i128(i128 %a, i128 %b) nounwind { ; X86-LABEL: test_i128: ; X86: # %bb.0: ; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %ebx ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: cmpl %edx, %ebx -; X86-NEXT: sbbl %esi, %ebp -; X86-NEXT: movl %eax, %ebp -; X86-NEXT: sbbl %ecx, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 40(%ebp), %ecx +; X86-NEXT: movl 44(%ebp), %edx +; X86-NEXT: movl 28(%ebp), %esi +; X86-NEXT: cmpl %ecx, 24(%ebp) +; X86-NEXT: sbbl %edx, %esi +; X86-NEXT: movl 48(%ebp), %esi +; X86-NEXT: movl 32(%ebp), %ebx +; X86-NEXT: sbbl %esi, %ebx +; X86-NEXT: movl 52(%ebp), %ebx +; X86-NEXT: movl 36(%ebp), %edi ; X86-NEXT: movl %edi, %eax -; X86-NEXT: sbbl %ebp, %eax -; X86-NEXT: cmovbl %ebx, %edx -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %esi -; X86-NEXT: cmovbl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: cmovbl %edi, %ebp -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %ebp, 12(%eax) -; X86-NEXT: movl %ecx, 8(%eax) -; X86-NEXT: movl %esi, 4(%eax) -; X86-NEXT: movl %edx, (%eax) +; X86-NEXT: sbbl %ebx, %eax +; X86-NEXT: cmovbl 24(%ebp), %ecx +; X86-NEXT: cmovbl 28(%ebp), %edx +; X86-NEXT: cmovbl 32(%ebp), %esi +; X86-NEXT: cmovbl %edi, %ebx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %ebx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: leal -12(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi ; X86-NEXT: popl %ebx @@ -727,29 +729,32 @@ define i128 @test_signbits_i128(i128 %a, i128 %b) nounwind { ; ; X86-LABEL: test_signbits_i128: ; X86: # %bb.0: -; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp ; X86-NEXT: pushl %edi ; X86-NEXT: pushl %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: shrdl $28, %edi, %ecx -; X86-NEXT: sarl $28, %edi +; X86-NEXT: andl $-16, %esp +; X86-NEXT: movl 32(%ebp), %esi +; X86-NEXT: movl 36(%ebp), %eax +; X86-NEXT: movl 48(%ebp), %ecx +; X86-NEXT: movl 52(%ebp), %edx +; X86-NEXT: shrdl $28, %edx, %ecx +; X86-NEXT: sarl $28, %edx ; X86-NEXT: cmpl %ecx, %esi -; X86-NEXT: movl %edx, %ebx -; X86-NEXT: sbbl %edi, %ebx +; X86-NEXT: movl %eax, %edi +; X86-NEXT: sbbl %edx, %edi ; X86-NEXT: cmovbl %esi, %ecx -; X86-NEXT: cmovbl %edx, %edi -; X86-NEXT: movl %edi, 4(%eax) -; X86-NEXT: sarl $31, %edi +; X86-NEXT: cmovbl %eax, %edx +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %edx, 4(%eax) ; X86-NEXT: movl %ecx, (%eax) -; X86-NEXT: movl %edi, 12(%eax) -; X86-NEXT: movl %edi, 8(%eax) +; X86-NEXT: sarl $31, %edx +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %edx, 8(%eax) +; X86-NEXT: leal -8(%ebp), %esp ; X86-NEXT: popl %esi ; X86-NEXT: popl %edi -; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp ; X86-NEXT: retl $4 %ax = ashr i128 %a, 64 %bx = ashr i128 %b, 92 diff --git a/llvm/test/CodeGen/X86/umulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/X86/umulo-128-legalisation-lowering.ll index 4c3170304b980..89afd1b00444b 100644 --- a/llvm/test/CodeGen/X86/umulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/X86/umulo-128-legalisation-lowering.ll @@ -38,8 +38,8 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 { ; X86-NEXT: .cfi_def_cfa_offset 16 ; X86-NEXT: pushl %esi ; X86-NEXT: .cfi_def_cfa_offset 20 -; X86-NEXT: subl $24, %esp -; X86-NEXT: .cfi_def_cfa_offset 44 +; X86-NEXT: subl $28, %esp +; X86-NEXT: .cfi_def_cfa_offset 48 ; X86-NEXT: .cfi_offset %esi, -20 ; X86-NEXT: .cfi_offset %edi, -16 ; X86-NEXT: .cfi_offset %ebx, -12 @@ -147,7 +147,7 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 { ; X86-NEXT: andb $1, %al ; X86-NEXT: movb %al, 16(%ecx) ; X86-NEXT: movl %ecx, %eax -; X86-NEXT: addl $24, %esp +; X86-NEXT: addl $28, %esp ; X86-NEXT: .cfi_def_cfa_offset 20 ; X86-NEXT: popl %esi ; X86-NEXT: .cfi_def_cfa_offset 16 diff --git a/llvm/test/CodeGen/X86/vec_extract.ll b/llvm/test/CodeGen/X86/vec_extract.ll index 087cd30abee9b..9bd38db3e9c4c 100644 --- a/llvm/test/CodeGen/X86/vec_extract.ll +++ b/llvm/test/CodeGen/X86/vec_extract.ll @@ -104,6 +104,72 @@ entry: } declare <2 x double> @foo() +define i64 @pr150117(<31 x i8> %a0) nounwind { +; X86-LABEL: pr150117: +; X86: # %bb.0: +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ebx +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-NEXT: shll $8, %edx +; X86-NEXT: orl %ebx, %edx +; X86-NEXT: shll $8, %edi +; X86-NEXT: orl %esi, %edi +; X86-NEXT: shll $16, %ecx +; X86-NEXT: orl %edi, %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %esi +; X86-NEXT: shll $24, %esi +; X86-NEXT: orl %ecx, %esi +; X86-NEXT: movd %esi, %xmm0 +; X86-NEXT: pinsrw $2, %edx, %xmm0 +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: shll $8, %ecx +; X86-NEXT: orl %eax, %ecx +; X86-NEXT: pinsrw $3, %ecx, %xmm0 +; X86-NEXT: movd %xmm0, %eax +; X86-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-NEXT: movd %xmm0, %edx +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: retl +; +; X64-LABEL: pr150117: +; X64: # %bb.0: +; X64-NEXT: movzbl {{[0-9]+}}(%rsp), %eax +; X64-NEXT: movzbl {{[0-9]+}}(%rsp), %ecx +; X64-NEXT: movzbl {{[0-9]+}}(%rsp), %edx +; X64-NEXT: movzbl {{[0-9]+}}(%rsp), %esi +; X64-NEXT: movzbl {{[0-9]+}}(%rsp), %edi +; X64-NEXT: movl {{[0-9]+}}(%rsp), %r8d +; X64-NEXT: shll $8, %r8d +; X64-NEXT: orl %edi, %r8d +; X64-NEXT: shll $8, %esi +; X64-NEXT: orl %edx, %esi +; X64-NEXT: shll $16, %ecx +; X64-NEXT: orl %esi, %ecx +; X64-NEXT: movl {{[0-9]+}}(%rsp), %edx +; X64-NEXT: shll $24, %edx +; X64-NEXT: orl %ecx, %edx +; X64-NEXT: movd %edx, %xmm0 +; X64-NEXT: pinsrw $2, %r8d, %xmm0 +; X64-NEXT: movl {{[0-9]+}}(%rsp), %ecx +; X64-NEXT: shll $8, %ecx +; X64-NEXT: orl %eax, %ecx +; X64-NEXT: pinsrw $3, %ecx, %xmm0 +; X64-NEXT: movq %xmm0, %rax +; X64-NEXT: retq + %shuffle = shufflevector <31 x i8> %a0, <31 x i8> zeroinitializer, <32 x i32> + %bitcast = bitcast <32 x i8> %shuffle to <4 x i64> + %elt = extractelement <4 x i64> %bitcast, i64 0 + ret i64 %elt +} + ; OSS-Fuzz #15662 ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15662 define <4 x i32> @ossfuzz15662(ptr %in) { diff --git a/llvm/test/CodeGen/X86/vector-shuffle-512-v64.ll b/llvm/test/CodeGen/X86/vector-shuffle-512-v64.ll index 87c135ddcec95..ef20cf2a09bba 100644 --- a/llvm/test/CodeGen/X86/vector-shuffle-512-v64.ll +++ b/llvm/test/CodeGen/X86/vector-shuffle-512-v64.ll @@ -1724,6 +1724,269 @@ define void @PR54562_mem(ptr %src, ptr %dst) { ret void } +define <512 x i8> @PR153457(<512 x i8> %a0, <512 x i8> %a1) nounwind { +; AVX512F-LABEL: PR153457: +; AVX512F: # %bb.0: +; AVX512F-NEXT: pushq %rbp +; AVX512F-NEXT: movq %rsp, %rbp +; AVX512F-NEXT: andq $-64, %rsp +; AVX512F-NEXT: subq $64, %rsp +; AVX512F-NEXT: movq %rdi, %rax +; AVX512F-NEXT: vpbroadcastq %xmm0, %ymm7 +; AVX512F-NEXT: vmovdqa {{.*#+}} ymm8 = [u,u,u,u,u,u,u,u,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0] +; AVX512F-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm6 +; AVX512F-NEXT: vextracti64x4 $1, %zmm2, %ymm7 +; AVX512F-NEXT: vpbroadcastd %xmm0, %ymm9 +; AVX512F-NEXT: vpblendvb %ymm8, %ymm7, %ymm9, %ymm8 +; AVX512F-NEXT: vextracti32x4 $2, %zmm5, %xmm7 +; AVX512F-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] +; AVX512F-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[0,2,4,6,8,10,12,13,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vextracti32x4 $2, %zmm4, %xmm9 +; AVX512F-NEXT: vmovdqa {{.*#+}} xmm10 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,128] +; AVX512F-NEXT: vpshufb %xmm10, %xmm9, %xmm9 +; AVX512F-NEXT: vpshufb {{.*#+}} xmm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,xmm0[5] +; AVX512F-NEXT: vpor %xmm11, %xmm9, %xmm9 +; AVX512F-NEXT: vpshufb %xmm10, %xmm1, %xmm10 +; AVX512F-NEXT: vpshufb {{.*#+}} xmm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,xmm0[1] +; AVX512F-NEXT: vpor %xmm11, %xmm10, %xmm10 +; AVX512F-NEXT: vpslld $24, %xmm0, %xmm11 +; AVX512F-NEXT: vinserti128 $1, %xmm11, %ymm0, %ymm11 +; AVX512F-NEXT: vextracti64x4 $1, %zmm3, %ymm3 +; AVX512F-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vpblendvb %ymm12, %ymm3, %ymm11, %ymm3 +; AVX512F-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; AVX512F-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[0,2,4,6,8,10,12,5,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vmovdqa 16(%rbp), %xmm11 +; AVX512F-NEXT: vpsrld $16, %xmm11, %xmm12 +; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm12[0] +; AVX512F-NEXT: vinserti64x4 $1, %ymm8, %zmm2, %zmm2 +; AVX512F-NEXT: vpmovzxdq {{.*#+}} xmm8 = xmm11[0],zero,xmm11[1],zero +; AVX512F-NEXT: vinserti128 $1, %xmm8, %ymm0, %ymm8 +; AVX512F-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4,5],ymm8[6,7] +; AVX512F-NEXT: vpsrld $24, %xmm11, %xmm8 +; AVX512F-NEXT: vinserti64x4 $1, %ymm3, %zmm8, %zmm3 +; AVX512F-NEXT: vinserti128 $1, %xmm11, %ymm10, %ymm8 +; AVX512F-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm8[0,1,2,3],zmm1[4,5,6,7] +; AVX512F-NEXT: vinserti128 $1, %xmm11, %ymm9, %ymm8 +; AVX512F-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,21,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vinserti64x4 $1, %ymm8, %zmm4, %zmm4 +; AVX512F-NEXT: vpsrlq $48, %xmm11, %xmm8 +; AVX512F-NEXT: vpunpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm8[0] +; AVX512F-NEXT: vinserti64x4 $1, %ymm7, %zmm5, %zmm5 +; AVX512F-NEXT: vpermq {{.*#+}} ymm7 = ymm0[0,1,2,0] +; AVX512F-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,u,u,u,u,u,u,u,u] +; AVX512F-NEXT: vpbroadcastb 16(%rbp), %ymm8 +; AVX512F-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3,4,5],ymm8[6,7] +; AVX512F-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm7[0,1,2,3],zmm0[4,5,6,7] +; AVX512F-NEXT: vpsrlq $56, %xmm11, %xmm7 +; AVX512F-NEXT: vmovdqa %ymm7, 416(%rdi) +; AVX512F-NEXT: vmovdqa %ymm6, 384(%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm0, (%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm5, 320(%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm3, 192(%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm2, 128(%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm4, 256(%rdi) +; AVX512F-NEXT: vmovdqa64 %zmm1, 64(%rdi) +; AVX512F-NEXT: movq %rbp, %rsp +; AVX512F-NEXT: popq %rbp +; AVX512F-NEXT: vzeroupper +; AVX512F-NEXT: retq +; +; AVX512BW-LABEL: PR153457: +; AVX512BW: # %bb.0: +; AVX512BW-NEXT: pushq %rbp +; AVX512BW-NEXT: movq %rsp, %rbp +; AVX512BW-NEXT: andq $-64, %rsp +; AVX512BW-NEXT: subq $64, %rsp +; AVX512BW-NEXT: movq %rdi, %rax +; AVX512BW-NEXT: vmovdqa64 16(%rbp), %zmm7 +; AVX512BW-NEXT: vpbroadcastq %xmm0, %ymm8 +; AVX512BW-NEXT: vmovdqa {{.*#+}} ymm9 = [u,u,u,u,u,u,u,u,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0] +; AVX512BW-NEXT: vpblendvb %ymm9, %ymm6, %ymm8, %ymm6 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm2, %ymm8 +; AVX512BW-NEXT: vpbroadcastd %xmm0, %ymm10 +; AVX512BW-NEXT: vpblendvb %ymm9, %ymm8, %ymm10, %ymm8 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[0,2,4,6,8,10,12,5,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm2, %zmm2 +; AVX512BW-NEXT: vextracti32x4 $2, %zmm5, %xmm8 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm8[0],xmm0[0],xmm8[1],xmm0[1],xmm8[2],xmm0[2],xmm8[3],xmm0[3],xmm8[4],xmm0[4],xmm8[5],xmm0[5],xmm8[6],xmm0[6],xmm8[7],xmm0[7] +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm8 = xmm8[0,2,4,6,8,10,12,13,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vinserti32x4 $2, %xmm8, %zmm5, %zmm5 +; AVX512BW-NEXT: vbroadcasti64x4 {{.*#+}} zmm8 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,128,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,128,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] +; AVX512BW-NEXT: # zmm8 = mem[0,1,2,3,0,1,2,3] +; AVX512BW-NEXT: vextracti32x4 $2, %zmm4, %xmm9 +; AVX512BW-NEXT: vpshufb %xmm8, %xmm9, %xmm9 +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm10 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,xmm0[5] +; AVX512BW-NEXT: vpor %xmm10, %xmm9, %xmm9 +; AVX512BW-NEXT: vinserti32x4 $2, %xmm9, %zmm4, %zmm4 +; AVX512BW-NEXT: vpslld $24, %xmm0, %xmm9 +; AVX512BW-NEXT: vinserti128 $1, %xmm9, %ymm0, %ymm9 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm3, %ymm3 +; AVX512BW-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vpblendvb %ymm10, %ymm3, %ymm9, %ymm3 +; AVX512BW-NEXT: vpshufb %zmm8, %zmm1, %zmm1 +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm8 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm0[1,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero +; AVX512BW-NEXT: vporq %zmm8, %zmm1, %zmm1 +; AVX512BW-NEXT: vinserti128 $1, %xmm7, %ymm1, %ymm8 +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm8[0,1,2,3],zmm1[4,5,6,7] +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm8 = [0,1,2,3,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,21,22,23,24,25,26,27,28,29,30,31] +; AVX512BW-NEXT: vpermi2w %zmm7, %zmm2, %zmm8 +; AVX512BW-NEXT: vpmovzxdq {{.*#+}} xmm2 = xmm7[0],zero,xmm7[1],zero +; AVX512BW-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm2 +; AVX512BW-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0,1,2,3,4,5],ymm2[6,7] +; AVX512BW-NEXT: vpsrld $24, %xmm7, %xmm3 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm3 +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm3 = zmm3[u,u,u,u,u,u,u,u,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,39,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vinserti32x4 $3, %xmm7, %zmm4, %zmm4 +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,53,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm6 = ymm0[0,1,2,0] +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,u,u,u,u,u,u,u,u] +; AVX512BW-NEXT: vpbroadcastb 16(%rbp), %ymm9 +; AVX512BW-NEXT: vpblendd {{.*#+}} ymm6 = ymm6[0,1,2,3,4,5],ymm9[6,7] +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm6[0,1,2,3],zmm0[4,5,6,7] +; AVX512BW-NEXT: vbroadcasti64x4 {{.*#+}} zmm6 = [16,17,18,19,35,0,0,0,8,9,10,11,12,13,14,15,16,17,18,19,35,0,0,0,8,9,10,11,12,13,14,15] +; AVX512BW-NEXT: # zmm6 = mem[0,1,2,3,0,1,2,3] +; AVX512BW-NEXT: vpermi2w %zmm7, %zmm5, %zmm6 +; AVX512BW-NEXT: vmovdqa64 %zmm6, 320(%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm3, 384(%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm0, (%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm4, 256(%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm2, 192(%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm8, 128(%rdi) +; AVX512BW-NEXT: vmovdqa64 %zmm1, 64(%rdi) +; AVX512BW-NEXT: movq %rbp, %rsp +; AVX512BW-NEXT: popq %rbp +; AVX512BW-NEXT: vzeroupper +; AVX512BW-NEXT: retq +; +; AVX512DQ-LABEL: PR153457: +; AVX512DQ: # %bb.0: +; AVX512DQ-NEXT: pushq %rbp +; AVX512DQ-NEXT: movq %rsp, %rbp +; AVX512DQ-NEXT: andq $-64, %rsp +; AVX512DQ-NEXT: subq $64, %rsp +; AVX512DQ-NEXT: movq %rdi, %rax +; AVX512DQ-NEXT: vpbroadcastq %xmm0, %ymm7 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm8 = [u,u,u,u,u,u,u,u,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0] +; AVX512DQ-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm6 +; AVX512DQ-NEXT: vextracti64x4 $1, %zmm2, %ymm7 +; AVX512DQ-NEXT: vpbroadcastd %xmm0, %ymm9 +; AVX512DQ-NEXT: vpblendvb %ymm8, %ymm7, %ymm9, %ymm8 +; AVX512DQ-NEXT: vextracti32x4 $2, %zmm5, %xmm7 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[0,2,4,6,8,10,12,13,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vextracti32x4 $2, %zmm4, %xmm9 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm10 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,128] +; AVX512DQ-NEXT: vpshufb %xmm10, %xmm9, %xmm9 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,xmm0[5] +; AVX512DQ-NEXT: vpor %xmm11, %xmm9, %xmm9 +; AVX512DQ-NEXT: vpshufb %xmm10, %xmm1, %xmm10 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,xmm0[1] +; AVX512DQ-NEXT: vpor %xmm11, %xmm10, %xmm10 +; AVX512DQ-NEXT: vpslld $24, %xmm0, %xmm11 +; AVX512DQ-NEXT: vinserti128 $1, %xmm11, %ymm0, %ymm11 +; AVX512DQ-NEXT: vextracti64x4 $1, %zmm3, %ymm3 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vpblendvb %ymm12, %ymm3, %ymm11, %ymm3 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[0,2,4,6,8,10,12,5,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vmovdqa 16(%rbp), %xmm11 +; AVX512DQ-NEXT: vpsrld $16, %xmm11, %xmm12 +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm12[0] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm2, %zmm2 +; AVX512DQ-NEXT: vpmovzxdq {{.*#+}} xmm8 = xmm11[0],zero,xmm11[1],zero +; AVX512DQ-NEXT: vinserti128 $1, %xmm8, %ymm0, %ymm8 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm3 = ymm3[0,1,2,3,4,5],ymm8[6,7] +; AVX512DQ-NEXT: vpsrld $24, %xmm11, %xmm8 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm8, %zmm3 +; AVX512DQ-NEXT: vinserti128 $1, %xmm11, %ymm10, %ymm8 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm8[0,1,2,3],zmm1[4,5,6,7] +; AVX512DQ-NEXT: vinserti128 $1, %xmm11, %ymm9, %ymm8 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm8[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,21,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm4, %zmm4 +; AVX512DQ-NEXT: vpsrlq $48, %xmm11, %xmm8 +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm7 = xmm7[0],xmm8[0] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm5, %zmm5 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm0[0,1,2,0] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,u,u,u,u,u,u,u,u] +; AVX512DQ-NEXT: vpbroadcastb 16(%rbp), %ymm8 +; AVX512DQ-NEXT: vpblendd {{.*#+}} ymm7 = ymm7[0,1,2,3,4,5],ymm8[6,7] +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm7[0,1,2,3],zmm0[4,5,6,7] +; AVX512DQ-NEXT: vpsrlq $56, %xmm11, %xmm7 +; AVX512DQ-NEXT: vmovdqa %ymm7, 416(%rdi) +; AVX512DQ-NEXT: vmovdqa %ymm6, 384(%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm0, (%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm5, 320(%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm3, 192(%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm2, 128(%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm4, 256(%rdi) +; AVX512DQ-NEXT: vmovdqa64 %zmm1, 64(%rdi) +; AVX512DQ-NEXT: movq %rbp, %rsp +; AVX512DQ-NEXT: popq %rbp +; AVX512DQ-NEXT: vzeroupper +; AVX512DQ-NEXT: retq +; +; AVX512VBMI-LABEL: PR153457: +; AVX512VBMI: # %bb.0: +; AVX512VBMI-NEXT: pushq %rbp +; AVX512VBMI-NEXT: movq %rsp, %rbp +; AVX512VBMI-NEXT: andq $-64, %rsp +; AVX512VBMI-NEXT: subq $64, %rsp +; AVX512VBMI-NEXT: movq %rdi, %rax +; AVX512VBMI-NEXT: vmovdqa64 16(%rbp), %zmm7 +; AVX512VBMI-NEXT: vbroadcasti64x4 {{.*#+}} zmm8 = [32,33,34,35,36,37,38,70,0,0,0,0,0,0,0,0,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,70,0,0,0,0,0,0,0,0,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31] +; AVX512VBMI-NEXT: # zmm8 = mem[0,1,2,3,0,1,2,3] +; AVX512VBMI-NEXT: vpermi2b %zmm0, %zmm5, %zmm8 +; AVX512VBMI-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = [32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,69,0,0,0,0,0,0,0,0,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,69,0,0,0,0,0,0,0,0,24,25,26,27,28,29,30,31] +; AVX512VBMI-NEXT: # zmm5 = mem[0,1,2,3,0,1,2,3] +; AVX512VBMI-NEXT: vpermi2b %zmm0, %zmm4, %zmm5 +; AVX512VBMI-NEXT: vbroadcasti64x4 {{.*#+}} zmm4 = [32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,68,0,0,0,0,0,0,0,0,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,68,0,0,0,0,0,0,0,0] +; AVX512VBMI-NEXT: # zmm4 = mem[0,1,2,3,0,1,2,3] +; AVX512VBMI-NEXT: vpermi2b %zmm0, %zmm3, %zmm4 +; AVX512VBMI-NEXT: vbroadcasti64x4 {{.*#+}} zmm3 = [0,1,2,3,4,5,6,66,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,67,0,1,2,3,4,5,6,66,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,67] +; AVX512VBMI-NEXT: # zmm3 = mem[0,1,2,3,0,1,2,3] +; AVX512VBMI-NEXT: vpermi2b %zmm0, %zmm2, %zmm3 +; AVX512VBMI-NEXT: vpshufb {{.*#+}} zmm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm0[1,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero +; AVX512VBMI-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14],zero,zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] +; AVX512VBMI-NEXT: vporq %zmm2, %zmm1, %zmm1 +; AVX512VBMI-NEXT: vmovdqa {{.*#+}} ymm2 = [u,u,u,u,u,u,u,u,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,71] +; AVX512VBMI-NEXT: vpermi2b %zmm0, %zmm6, %zmm2 +; AVX512VBMI-NEXT: vmovdqa64 {{.*#+}} zmm6 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,0,64,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57,58,59,60,61,62,63] +; AVX512VBMI-NEXT: vpermi2b %zmm7, %zmm0, %zmm6 +; AVX512VBMI-NEXT: vpmovsxbw {{.*#+}} zmm0 = [0,1,2,3,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,21,22,23,24,25,26,27,28,29,30,31] +; AVX512VBMI-NEXT: vpermi2w %zmm7, %zmm3, %zmm0 +; AVX512VBMI-NEXT: vmovdqa64 {{.*#+}} zmm3 = [67,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,68,u,u,u,u,u,u,u] +; AVX512VBMI-NEXT: vpermi2b %zmm7, %zmm4, %zmm3 +; AVX512VBMI-NEXT: vinserti32x4 $3, %xmm7, %zmm5, %zmm4 +; AVX512VBMI-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,53,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512VBMI-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = [16,17,18,19,35,0,0,0,8,9,10,11,12,13,14,15,16,17,18,19,35,0,0,0,8,9,10,11,12,13,14,15] +; AVX512VBMI-NEXT: # zmm5 = mem[0,1,2,3,0,1,2,3] +; AVX512VBMI-NEXT: vpermi2w %zmm7, %zmm8, %zmm5 +; AVX512VBMI-NEXT: vinserti64x4 $1, %ymm7, %zmm2, %zmm2 +; AVX512VBMI-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,39,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u] +; AVX512VBMI-NEXT: vmovdqa64 {{.*#+}} zmm8 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,65,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63] +; AVX512VBMI-NEXT: vpermi2b %zmm7, %zmm1, %zmm8 +; AVX512VBMI-NEXT: vmovdqa64 %zmm5, 320(%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm4, 256(%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm3, 192(%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm0, 128(%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm8, 64(%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm6, (%rdi) +; AVX512VBMI-NEXT: vmovdqa64 %zmm2, 384(%rdi) +; AVX512VBMI-NEXT: movq %rbp, %rsp +; AVX512VBMI-NEXT: popq %rbp +; AVX512VBMI-NEXT: vzeroupper +; AVX512VBMI-NEXT: retq + %shuffle1 = shufflevector <512 x i8> %a0, <512 x i8> zeroinitializer, <512 x i32> + %shuffle2 = shufflevector <512 x i8> %shuffle1, <512 x i8> %a1, <512 x i32> + ret <512 x i8> %shuffle2 +} + define <64 x i8> @shuffle_v32i16_zextinreg_to_v16i32(<64 x i8> %a) { ; ALL-LABEL: shuffle_v32i16_zextinreg_to_v16i32: ; ALL: # %bb.0: diff --git a/llvm/test/CodeGen/X86/wide-integer-cmp.ll b/llvm/test/CodeGen/X86/wide-integer-cmp.ll index a15d633d85381..12dccca76eb19 100644 --- a/llvm/test/CodeGen/X86/wide-integer-cmp.ll +++ b/llvm/test/CodeGen/X86/wide-integer-cmp.ll @@ -92,6 +92,8 @@ define i32 @test_wide(i128 %a, i128 %b) { ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: pushl %esi ; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: subl $8, %esp +; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: .cfi_offset %esi, -8 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx @@ -101,15 +103,15 @@ define i32 @test_wide(i128 %a, i128 %b) { ; CHECK-NEXT: sbbl {{[0-9]+}}(%esp), %esi ; CHECK-NEXT: sbbl {{[0-9]+}}(%esp), %ecx ; CHECK-NEXT: sbbl {{[0-9]+}}(%esp), %eax -; CHECK-NEXT: jge .LBB4_2 +; CHECK-NEXT: jge .LBB4_3 ; CHECK-NEXT: # %bb.1: # %bb1 ; CHECK-NEXT: movl $1, %eax -; CHECK-NEXT: popl %esi -; CHECK-NEXT: .cfi_def_cfa_offset 4 -; CHECK-NEXT: retl -; CHECK-NEXT: .LBB4_2: # %bb2 -; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: jmp .LBB4_2 +; CHECK-NEXT: .LBB4_3: # %bb2 ; CHECK-NEXT: movl $2, %eax +; CHECK-NEXT: .LBB4_2: # %bb1 +; CHECK-NEXT: addl $8, %esp +; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: popl %esi ; CHECK-NEXT: .cfi_def_cfa_offset 4 ; CHECK-NEXT: retl diff --git a/llvm/test/CodeGen/X86/win32-int-runtime-libcalls.ll b/llvm/test/CodeGen/X86/win32-int-runtime-libcalls.ll new file mode 100644 index 0000000000000..5ac90a0af2e57 --- /dev/null +++ b/llvm/test/CodeGen/X86/win32-int-runtime-libcalls.ll @@ -0,0 +1,113 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck -check-prefix=CHECK32 %s +; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck -check-prefix=CHECK64 %s + +define i64 @test_sdiv_i64(i64 %a, i64 %b) { +; CHECK32-LABEL: test_sdiv_i64: +; CHECK32: # %bb.0: +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: calll __alldiv +; CHECK32-NEXT: retl +; +; CHECK64-LABEL: test_sdiv_i64: +; CHECK64: # %bb.0: +; CHECK64-NEXT: movq %rdx, %r8 +; CHECK64-NEXT: movq %rcx, %rax +; CHECK64-NEXT: cqto +; CHECK64-NEXT: idivq %r8 +; CHECK64-NEXT: retq + %ret = sdiv i64 %a, %b + ret i64 %ret +} + +define i64 @test_srem_i64(i64 %a, i64 %b) { +; CHECK32-LABEL: test_srem_i64: +; CHECK32: # %bb.0: +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: calll __allrem +; CHECK32-NEXT: retl +; +; CHECK64-LABEL: test_srem_i64: +; CHECK64: # %bb.0: +; CHECK64-NEXT: movq %rdx, %r8 +; CHECK64-NEXT: movq %rcx, %rax +; CHECK64-NEXT: cqto +; CHECK64-NEXT: idivq %r8 +; CHECK64-NEXT: movq %rdx, %rax +; CHECK64-NEXT: retq + %ret = srem i64 %a, %b + ret i64 %ret +} + +define i64 @test_udiv_i64(i64 %a, i64 %b) { +; CHECK32-LABEL: test_udiv_i64: +; CHECK32: # %bb.0: +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: calll __aulldiv +; CHECK32-NEXT: retl +; +; CHECK64-LABEL: test_udiv_i64: +; CHECK64: # %bb.0: +; CHECK64-NEXT: movq %rdx, %r8 +; CHECK64-NEXT: movq %rcx, %rax +; CHECK64-NEXT: xorl %edx, %edx +; CHECK64-NEXT: divq %r8 +; CHECK64-NEXT: retq + %ret = udiv i64 %a, %b + ret i64 %ret +} + +define i64 @test_urem_i64(i64 %a, i64 %b) { +; CHECK32-LABEL: test_urem_i64: +; CHECK32: # %bb.0: +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: pushl {{[0-9]+}}(%esp) +; CHECK32-NEXT: calll __aullrem +; CHECK32-NEXT: retl +; +; CHECK64-LABEL: test_urem_i64: +; CHECK64: # %bb.0: +; CHECK64-NEXT: movq %rdx, %r8 +; CHECK64-NEXT: movq %rcx, %rax +; CHECK64-NEXT: xorl %edx, %edx +; CHECK64-NEXT: divq %r8 +; CHECK64-NEXT: movq %rdx, %rax +; CHECK64-NEXT: retq + %ret = urem i64 %a, %b + ret i64 %ret +} + +define i64 @test_mul_i64(i64 %a, i64 %b) { +; CHECK32-LABEL: test_mul_i64: +; CHECK32: # %bb.0: +; CHECK32-NEXT: pushl %esi +; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi +; CHECK32-NEXT: movl %ecx, %eax +; CHECK32-NEXT: mull %esi +; CHECK32-NEXT: imull {{[0-9]+}}(%esp), %ecx +; CHECK32-NEXT: addl %ecx, %edx +; CHECK32-NEXT: imull {{[0-9]+}}(%esp), %esi +; CHECK32-NEXT: addl %esi, %edx +; CHECK32-NEXT: popl %esi +; CHECK32-NEXT: retl +; +; CHECK64-LABEL: test_mul_i64: +; CHECK64: # %bb.0: +; CHECK64-NEXT: movq %rcx, %rax +; CHECK64-NEXT: imulq %rdx, %rax +; CHECK64-NEXT: retq + %ret = mul i64 %a, %b + ret i64 %ret +} diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll new file mode 100644 index 0000000000000..d9253e0ca127b --- /dev/null +++ b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll @@ -0,0 +1,216 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 -verify-machineinstrs | FileCheck %s --check-prefixes=SSE +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx -verify-machineinstrs | FileCheck %s --check-prefixes=AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 -verify-machineinstrs | FileCheck %s --check-prefixes=AVX,AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512vl -verify-machineinstrs | FileCheck %s --check-prefixes=AVX512,AVX512VL +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512vl,+avx512bw -verify-machineinstrs | FileCheck %s --check-prefixes=AVX512,AVX512BW + +define void @zero_xmm(<4 x i32> %arg) #0 { +; SSE-LABEL: zero_xmm: +; SSE: # %bb.0: +; SSE-NEXT: movaps %xmm0, 0 +; SSE-NEXT: xorps %xmm0, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: zero_xmm: +; AVX: # %bb.0: +; AVX-NEXT: vmovaps %xmm0, 0 +; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX-NEXT: retq +; +; AVX512-LABEL: zero_xmm: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovaps %xmm0, 0 +; AVX512-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX512-NEXT: retq + store <4 x i32> %arg, ptr null, align 32 + ret void +} + +define void @zero_ymm(<8 x i32> %arg) #0 { +; SSE-LABEL: zero_ymm: +; SSE: # %bb.0: +; SSE-NEXT: movaps %xmm1, 16 +; SSE-NEXT: movaps %xmm0, 0 +; SSE-NEXT: xorps %xmm0, %xmm0 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: retq +; +; AVX-LABEL: zero_ymm: +; AVX: # %bb.0: +; AVX-NEXT: vmovaps %ymm0, 0 +; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX-NEXT: vzeroupper +; AVX-NEXT: retq +; +; AVX512-LABEL: zero_ymm: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovaps %ymm0, 0 +; AVX512-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + store <8 x i32> %arg, ptr null, align 32 + ret void +} + +define void @zero_zmm(<16 x i32> %arg) #0 { +; SSE-LABEL: zero_zmm: +; SSE: # %bb.0: +; SSE-NEXT: movaps %xmm3, 48 +; SSE-NEXT: movaps %xmm2, 32 +; SSE-NEXT: movaps %xmm1, 16 +; SSE-NEXT: movaps %xmm0, 0 +; SSE-NEXT: xorps %xmm0, %xmm0 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: xorps %xmm2, %xmm2 +; SSE-NEXT: xorps %xmm3, %xmm3 +; SSE-NEXT: retq +; +; AVX-LABEL: zero_zmm: +; AVX: # %bb.0: +; AVX-NEXT: vmovaps %ymm1, 32 +; AVX-NEXT: vmovaps %ymm0, 0 +; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +; AVX-NEXT: vzeroupper +; AVX-NEXT: retq +; +; AVX512-LABEL: zero_zmm: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovups %zmm0, 0 +; AVX512-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + store <16 x i32> %arg, ptr null, align 32 + ret void +} + +define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 { +; SSE-LABEL: zero_k: +; SSE: # %bb.0: +; SSE-NEXT: psllw $15, %xmm2 +; SSE-NEXT: packsswb %xmm2, %xmm2 +; SSE-NEXT: pmovmskb %xmm2, %eax +; SSE-NEXT: testb $1, %al +; SSE-NEXT: jne .LBB3_1 +; SSE-NEXT: # %bb.2: # %else +; SSE-NEXT: testb $2, %al +; SSE-NEXT: jne .LBB3_3 +; SSE-NEXT: .LBB3_4: # %else2 +; SSE-NEXT: testb $4, %al +; SSE-NEXT: jne .LBB3_5 +; SSE-NEXT: .LBB3_6: # %else4 +; SSE-NEXT: testb $8, %al +; SSE-NEXT: jne .LBB3_7 +; SSE-NEXT: .LBB3_8: # %else6 +; SSE-NEXT: testb $16, %al +; SSE-NEXT: jne .LBB3_9 +; SSE-NEXT: .LBB3_10: # %else8 +; SSE-NEXT: testb $32, %al +; SSE-NEXT: jne .LBB3_11 +; SSE-NEXT: .LBB3_12: # %else10 +; SSE-NEXT: testb $64, %al +; SSE-NEXT: jne .LBB3_13 +; SSE-NEXT: .LBB3_14: # %else12 +; SSE-NEXT: testb $-128, %al +; SSE-NEXT: je .LBB3_16 +; SSE-NEXT: .LBB3_15: # %cond.store13 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[3,3,3,3] +; SSE-NEXT: movd %xmm0, 28 +; SSE-NEXT: .LBB3_16: # %else14 +; SSE-NEXT: xorl %eax, %eax +; SSE-NEXT: pxor %xmm0, %xmm0 +; SSE-NEXT: pxor %xmm1, %xmm1 +; SSE-NEXT: pxor %xmm2, %xmm2 +; SSE-NEXT: retq +; SSE-NEXT: .LBB3_1: # %cond.store +; SSE-NEXT: movd %xmm0, 0 +; SSE-NEXT: testb $2, %al +; SSE-NEXT: je .LBB3_4 +; SSE-NEXT: .LBB3_3: # %cond.store1 +; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,1,1] +; SSE-NEXT: movd %xmm2, 4 +; SSE-NEXT: testb $4, %al +; SSE-NEXT: je .LBB3_6 +; SSE-NEXT: .LBB3_5: # %cond.store3 +; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE-NEXT: movd %xmm2, 8 +; SSE-NEXT: testb $8, %al +; SSE-NEXT: je .LBB3_8 +; SSE-NEXT: .LBB3_7: # %cond.store5 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[3,3,3,3] +; SSE-NEXT: movd %xmm0, 12 +; SSE-NEXT: testb $16, %al +; SSE-NEXT: je .LBB3_10 +; SSE-NEXT: .LBB3_9: # %cond.store7 +; SSE-NEXT: movd %xmm1, 16 +; SSE-NEXT: testb $32, %al +; SSE-NEXT: je .LBB3_12 +; SSE-NEXT: .LBB3_11: # %cond.store9 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1] +; SSE-NEXT: movd %xmm0, 20 +; SSE-NEXT: testb $64, %al +; SSE-NEXT: je .LBB3_14 +; SSE-NEXT: .LBB3_13: # %cond.store11 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE-NEXT: movd %xmm0, 24 +; SSE-NEXT: testb $-128, %al +; SSE-NEXT: jne .LBB3_15 +; SSE-NEXT: jmp .LBB3_16 +; +; AVX1-LABEL: zero_k: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX1-NEXT: vpslld $31, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm1 = xmm1[4,4,5,5,6,6,7,7] +; AVX1-NEXT: vpslld $31, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: vmaskmovps %ymm0, %ymm1, 0 +; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vzeroupper +; AVX1-NEXT: retq +; +; AVX2-LABEL: zero_k: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX2-NEXT: vpslld $31, %ymm1, %ymm1 +; AVX2-NEXT: vpmaskmovd %ymm0, %ymm1, 0 +; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX2-NEXT: vpxor %xmm0, %xmm0, %xmm0 +; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512VL-LABEL: zero_k: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX512VL-NEXT: vpslld $31, %ymm1, %ymm1 +; AVX512VL-NEXT: vptestmd %ymm1, %ymm1, %k1 +; AVX512VL-NEXT: vmovdqa32 %ymm0, 0 {%k1} +; AVX512VL-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX512VL-NEXT: vpxor %xmm0, %xmm0, %xmm0 +; AVX512VL-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX512VL-NEXT: kxorw %k0, %k0, %k1 +; AVX512VL-NEXT: vzeroupper +; AVX512VL-NEXT: retq +; +; AVX512BW-LABEL: zero_k: +; AVX512BW: # %bb.0: +; AVX512BW-NEXT: vpsllw $15, %xmm1, %xmm1 +; AVX512BW-NEXT: vpmovw2m %xmm1, %k1 +; AVX512BW-NEXT: vmovdqa32 %ymm0, 0 {%k1} +; AVX512BW-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX512BW-NEXT: vpxor %xmm0, %xmm0, %xmm0 +; AVX512BW-NEXT: kxorq %k0, %k0, %k1 +; AVX512BW-NEXT: vzeroupper +; AVX512BW-NEXT: retq + tail call void @llvm.masked.store.v8i32.p0(<8 x i32> %arg, ptr null, i32 32, <8 x i1> %mask) + ret void +} + +attributes #0 = { "zero-call-used-regs"="used" } diff --git a/llvm/test/CodeGen/Xtensa/select-cc-fp.ll b/llvm/test/CodeGen/Xtensa/select-cc-fp.ll index ee45ef006123c..742770de23f37 100644 --- a/llvm/test/CodeGen/Xtensa/select-cc-fp.ll +++ b/llvm/test/CodeGen/Xtensa/select-cc-fp.ll @@ -103,8 +103,8 @@ define float @brcc_olt(float %a, float %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: wfr f8, a3 ; CHECK-NEXT: wfr f9, a2 -; CHECK-NEXT: ule.s b0, f8, f9 -; CHECK-NEXT: bt b0, .LBB3_2 +; CHECK-NEXT: olt.s b0, f9, f8 +; CHECK-NEXT: bf b0, .LBB3_2 ; CHECK-NEXT: # %bb.1: # %t1 ; CHECK-NEXT: l32r a8, .LCPI3_1 ; CHECK-NEXT: wfr f8, a8 @@ -135,8 +135,8 @@ define float @brcc_ole(float %a, float %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: wfr f8, a3 ; CHECK-NEXT: wfr f9, a2 -; CHECK-NEXT: ult.s b0, f8, f9 -; CHECK-NEXT: bt b0, .LBB4_2 +; CHECK-NEXT: ole.s b0, f9, f8 +; CHECK-NEXT: bf b0, .LBB4_2 ; CHECK-NEXT: # %bb.1: # %t1 ; CHECK-NEXT: l32r a8, .LCPI4_1 ; CHECK-NEXT: wfr f8, a8 @@ -232,7 +232,7 @@ define float @brcc_ueq(float %a, float %b) nounwind { ; CHECK-NEXT: wfr f8, a3 ; CHECK-NEXT: wfr f9, a2 ; CHECK-NEXT: ueq.s b0, f9, f8 -; CHECK-NEXT: bt b0, .LBB7_2 +; CHECK-NEXT: bf b0, .LBB7_2 ; CHECK-NEXT: # %bb.1: # %t1 ; CHECK-NEXT: l32r a8, .LCPI7_1 ; CHECK-NEXT: wfr f8, a8 @@ -327,8 +327,8 @@ define float @brcc_ult(float %a, float %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: wfr f8, a3 ; CHECK-NEXT: wfr f9, a2 -; CHECK-NEXT: ole.s b0, f8, f9 -; CHECK-NEXT: bt b0, .LBB10_2 +; CHECK-NEXT: ult.s b0, f9, f8 +; CHECK-NEXT: bf b0, .LBB10_2 ; CHECK-NEXT: # %bb.1: # %t1 ; CHECK-NEXT: l32r a8, .LCPI10_1 ; CHECK-NEXT: wfr f8, a8 @@ -359,8 +359,8 @@ define float @brcc_ule(float %a, float %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: wfr f8, a3 ; CHECK-NEXT: wfr f9, a2 -; CHECK-NEXT: olt.s b0, f8, f9 -; CHECK-NEXT: bt b0, .LBB11_2 +; CHECK-NEXT: ule.s b0, f9, f8 +; CHECK-NEXT: bf b0, .LBB11_2 ; CHECK-NEXT: # %bb.1: # %t1 ; CHECK-NEXT: l32r a8, .LCPI11_1 ; CHECK-NEXT: wfr f8, a8 @@ -451,6 +451,21 @@ exit: } define float @copysign_f32(float %a, float %b) { +; CHECK-LABEL: copysign_f32: +; CHECK: .cfi_startproc +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: l32r a8, .LCPI14_0 +; CHECK-NEXT: and a8, a3, a8 +; CHECK-NEXT: l32r a9, .LCPI14_1 +; CHECK-NEXT: and a9, a2, a9 +; CHECK-NEXT: wfr f8, a9 +; CHECK-NEXT: movi a9, 0 +; CHECK-NEXT: beq a8, a9, .LBB14_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: neg.s f8, f8 +; CHECK-NEXT: .LBB14_2: # %entry +; CHECK-NEXT: rfr a2, f8 +; CHECK-NEXT: ret entry: %c = call float @llvm.copysign.f32(float %a, float %b) ret float %c diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/verify.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/verify.ll index 0f8f505c51a58..5d73b2669ccda 100644 --- a/llvm/test/DebugInfo/KeyInstructions/Generic/verify.ll +++ b/llvm/test/DebugInfo/KeyInstructions/Generic/verify.ll @@ -7,6 +7,8 @@ define dso_local void @f() !dbg !10 { entry: +; Include non-key location to check verifier is checking the whole function. + %0 = add i32 0, 0, !dbg !14 ret void, !dbg !13 } @@ -20,3 +22,4 @@ entry: !11 = !DISubroutineType(types: !12) !12 = !{null} !13 = !DILocation(line: 1, column: 11, scope: !10, atomGroup: 1, atomRank: 1) +!14 = !DILocation(line: 1, column: 11, scope: !10) diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_attrib_declare.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_attrib_declare.ll new file mode 100644 index 0000000000000..3526a010ce489 --- /dev/null +++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_attrib_declare.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -passes='rtsan' -S | FileCheck %s + +declare void @declared_realtime_function() sanitize_realtime #0 + +declare void @declared_blocking_function() sanitize_realtime_blocking #0 + +; RealtimeSanitizer pass should ignore attributed functions that are just declarations +; CHECK: declared_realtime_function +; CHECK-EMPTY: +; CHECK: declared_blocking_function +; CHECK-EMPTY: diff --git a/llvm/test/Instrumentation/SanitizerCoverage/missing_dbg.ll b/llvm/test/Instrumentation/SanitizerCoverage/missing_dbg.ll index 35684346c4d5a..07b9a1ce496d9 100644 --- a/llvm/test/Instrumentation/SanitizerCoverage/missing_dbg.ll +++ b/llvm/test/Instrumentation/SanitizerCoverage/missing_dbg.ll @@ -1,5 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 -S | FileCheck %s +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-stack-depth -sanitizer-coverage-stack-depth-callback-min=1 -S | FileCheck %s --check-prefix=CHECK-STACK-CALLBACK +; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=1 -sanitizer-coverage-stack-depth -S | FileCheck %s --check-prefix=CHECK-STACK-DEPTH 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" @@ -55,6 +57,86 @@ entry: ret i32 %t } +define i32 @with_dbg_stack_callback(ptr %a) !dbg !8 { +; CHECK-STACK-CALLBACK-LABEL: define i32 @with_dbg_stack_callback( +; CHECK-STACK-CALLBACK-SAME: ptr [[A:%.*]]) !dbg [[DBG8:![0-9]+]] { +; CHECK-STACK-CALLBACK-NEXT: entry: +; CHECK-STACK-CALLBACK-NEXT: [[BUF:%.*]] = alloca [64 x i8], align 1 +; CHECK-STACK-CALLBACK-NEXT: call void @__sanitizer_cov_stack_depth() #[[ATTR1:[0-9]+]], !dbg [[DBG9:![0-9]+]] +; CHECK-STACK-CALLBACK-NEXT: %t = load i32, ptr [[A]], align 4 +; CHECK-STACK-CALLBACK-NEXT: call void @external_func() +; CHECK-STACK-CALLBACK-NEXT: ret i32 %t +; +entry: + %buf = alloca [64 x i8], align 1 + %t = load i32, ptr %a, align 4 + call void @external_func() + ret i32 %t +} + +define i32 @with_dbg_stack_depth(ptr %a) !dbg !10 { +; CHECK-STACK-DEPTH-LABEL: define i32 @with_dbg_stack_depth( +; CHECK-STACK-DEPTH-SAME: ptr [[A:%.*]]) !dbg [[DBG10:![0-9]+]] { +; CHECK-STACK-DEPTH-NEXT: entry: +; CHECK-STACK-DEPTH-NEXT: [[BUF:%.*]] = alloca [64 x i8], align 1 +; CHECK-STACK-DEPTH-NEXT: [[TMP1:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; CHECK-STACK-DEPTH-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; CHECK-STACK-DEPTH-NEXT: [[TMP3:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8 +; CHECK-STACK-DEPTH-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]] +; CHECK-STACK-DEPTH-NEXT: br i1 [[TMP4]], label {{%.*}}, label {{%.*}} +; CHECK-STACK-DEPTH: store i64 [[TMP2]], ptr @__sancov_lowest_stack, align 8, !dbg [[DBG11:![0-9]+]], {{.*}}!nosanitize +; CHECK-STACK-DEPTH: %t = load i32, ptr [[A]], align 4 +; CHECK-STACK-DEPTH-NEXT: call void @external_func() +; CHECK-STACK-DEPTH-NEXT: ret i32 %t +; +entry: + %buf = alloca [64 x i8], align 1 + %t = load i32, ptr %a, align 4 + call void @external_func() + ret i32 %t +} + +define i32 @without_dbg_stack_callback(ptr %a) { +; CHECK-STACK-CALLBACK-LABEL: define i32 @without_dbg_stack_callback( +; CHECK-STACK-CALLBACK-SAME: ptr [[A:%.*]]) { +; CHECK-STACK-CALLBACK-NEXT: entry: +; CHECK-STACK-CALLBACK-NEXT: [[BUF:%.*]] = alloca [64 x i8], align 1 +; CHECK-STACK-CALLBACK-NEXT: call void @__sanitizer_cov_stack_depth() #[[ATTR1]] +; CHECK-STACK-CALLBACK-NEXT: %t = load i32, ptr [[A]], align 4 +; CHECK-STACK-CALLBACK-NEXT: call void @external_func() +; CHECK-STACK-CALLBACK-NEXT: ret i32 %t +; +entry: + %buf = alloca [64 x i8], align 1 + %t = load i32, ptr %a, align 4 + call void @external_func() + ret i32 %t +} + +define i32 @without_dbg_stack_depth(ptr %a) { +; CHECK-STACK-DEPTH-LABEL: define i32 @without_dbg_stack_depth( +; CHECK-STACK-DEPTH-SAME: ptr [[A:%.*]]) { +; CHECK-STACK-DEPTH-NEXT: entry: +; CHECK-STACK-DEPTH-NEXT: [[BUF:%.*]] = alloca [64 x i8], align 1 +; CHECK-STACK-DEPTH-NEXT: [[TMP1:%.*]] = call ptr @llvm.frameaddress.p0(i32 0) +; CHECK-STACK-DEPTH-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 +; CHECK-STACK-DEPTH-NEXT: [[TMP3:%.*]] = load i64, ptr @__sancov_lowest_stack, align 8 +; CHECK-STACK-DEPTH-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]] +; CHECK-STACK-DEPTH-NEXT: br i1 [[TMP4]], label {{%.*}}, label {{%.*}} +; CHECK-STACK-DEPTH: store i64 [[TMP2]], ptr @__sancov_lowest_stack, align 8, {{.*}}!nosanitize +; CHECK-STACK-DEPTH: %t = load i32, ptr [[A]], align 4 +; CHECK-STACK-DEPTH-NEXT: call void @external_func() +; CHECK-STACK-DEPTH-NEXT: ret i32 %t +; +entry: + %buf = alloca [64 x i8], align 1 + %t = load i32, ptr %a, align 4 + call void @external_func() + ret i32 %t +} + +declare void @external_func() + !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!2} @@ -66,6 +148,10 @@ entry: !5 = !{} !6 = !DILocation(line: 192, scope: !3) !7 = !DILocation(line: 0, scope: !3) +!8 = distinct !DISubprogram(name: "with_dbg_stack_callback", scope: !1, file: !1, line: 200, type: !4, scopeLine: 200, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!9 = !DILocation(line: 200, scope: !8) +!10 = distinct !DISubprogram(name: "with_dbg_stack_depth", scope: !1, file: !1, line: 210, type: !4, scopeLine: 210, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = !DILocation(line: 210, scope: !10) ;. ; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C89, file: [[META1:![0-9]+]], isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None) @@ -76,3 +162,9 @@ entry: ; CHECK: [[DBG6]] = !DILocation(line: 192, scope: [[DBG3]]) ; CHECK: [[DBG7]] = !DILocation(line: 0, scope: [[DBG3]]) ;. +; CHECK-STACK-CALLBACK: [[DBG8]] = distinct !DISubprogram(name: "with_dbg_stack_callback", scope: {{.*}}, file: {{.*}}, line: 200 +; CHECK-STACK-CALLBACK: [[DBG9]] = !DILocation(line: 200, scope: [[DBG8]]) +;. +; CHECK-STACK-DEPTH: [[DBG10]] = distinct !DISubprogram(name: "with_dbg_stack_depth", scope: {{.*}}, file: {{.*}}, line: 210 +; CHECK-STACK-DEPTH: [[DBG11]] = !DILocation(line: 210, scope: [[DBG10]]) +;. diff --git a/llvm/test/MC/ELF/cgprofile.s b/llvm/test/MC/ELF/cgprofile.s index f8469ddc68877..28d8b72185556 100644 --- a/llvm/test/MC/ELF/cgprofile.s +++ b/llvm/test/MC/ELF/cgprofile.s @@ -5,11 +5,11 @@ a: .word b .cg_profile a, b, 32 .cg_profile freq, a, 11 - .cg_profile late, late2, 20 + .cg_profile "late\\", late2, 20 .cg_profile .L.local, b, 42 - .globl late -late: + .globl "late\\" +"late\\": late2: .word 0 late3: .L.local: @@ -31,7 +31,7 @@ late3: # CHECK-NEXT: 0010: 14000000 00000000 2A000000 00000000 # CHECK-NEXT: ) -# CHECK: Name: .rel.llvm.call-graph-profile (28) +# CHECK: Name: .rel.llvm.call-graph-profile # CHECK-NEXT: Type: SHT_REL (0x9) # CHECK-NEXT: Flags [ (0x40) # CHECK-NEXT: SHF_INFO_LINK @@ -83,7 +83,7 @@ late3: # CHECK-NEXT: Type: # CHECK-NEXT: Other: # CHECK-NEXT: Section: Undefined -# CHECK: Name: late +# CHECK: Name: late\ ([[#]]) # CHECK-NEXT: Value: # CHECK-NEXT: Size: # CHECK-NEXT: Binding: Global diff --git a/llvm/test/MC/ELF/symbol-names.s b/llvm/test/MC/ELF/symbol-names.s index 427187c329acf..f1593dd2f8099 100644 --- a/llvm/test/MC/ELF/symbol-names.s +++ b/llvm/test/MC/ELF/symbol-names.s @@ -5,6 +5,7 @@ // CHECK-LABEL:SYMBOL TABLE: // CHECK-NEXT: 0000000000000001 l F .text 0000000000000000 a"b\{{$}} // CHECK-NEXT: 0000000000000006 l .text 0000000000000000 a\{{$}} +// CHECK-NEXT: 000000000000000b l .text 0000000000000000 a\\{{$}} // CHECK-NEXT: 0000000000000000 g F .text 0000000000000000 foo?bar // CHECK-NEXT: 0000000000000000 *UND* 0000000000000000 a"b\q{{$}} // CHECK-EMPTY: @@ -26,3 +27,5 @@ ret "a\\": /// GAS emits a warning for \q call "a\"b\q" + +"a\\\\" = . diff --git a/llvm/test/MC/Hexagon/system-inst.s b/llvm/test/MC/Hexagon/system-inst.s index 7bc1533598532..07f7ca0acb2dc 100644 --- a/llvm/test/MC/Hexagon/system-inst.s +++ b/llvm/test/MC/Hexagon/system-inst.s @@ -89,6 +89,9 @@ crswap(r12,sgp0) #CHECK: 652dc000 { crswap(r13,sgp1) } crswap(r13,sgp1) +#CHECK: 6d8ec000 { crswap(r15:14,s1:0) } +crswap(r15:14,sgp1:0) + #CHECK: 660fc00e { r14 = getimask(r15) } r14=getimask(r15) diff --git a/llvm/test/MC/Hexagon/two_ext.s b/llvm/test/MC/Hexagon/two_ext.s index 28b2aa3f1ecae..09b51c5f029a7 100644 --- a/llvm/test/MC/Hexagon/two_ext.s +++ b/llvm/test/MC/Hexagon/two_ext.s @@ -6,7 +6,7 @@ if (!p1) call foo_b } # CHECK: 00004000 { immext(#0) -# CHECK: 5d004100 if (p1) call 0x0 +# CHECK: 5d004100 if (p1) call 0x0 <.text> # CHECK: 00004000 immext(#0) -# CHECK: 5d20c100 if (!p1) call 0x0 } +# CHECK: 5d20c100 if (!p1) call 0x0 <.text> } diff --git a/llvm/test/MC/Mips/branch-pseudos-bad.s b/llvm/test/MC/Mips/branch-pseudos-bad.s index c23164d904619..9633414d84f4a 100644 --- a/llvm/test/MC/Mips/branch-pseudos-bad.s +++ b/llvm/test/MC/Mips/branch-pseudos-bad.s @@ -1,5 +1,13 @@ # RUN: not llvm-mc %s -triple=mips -mcpu=mips32 2>&1 | FileCheck %s +# CHECK: error: invalid operand for instruction + beql $t0, ($t0), 1 +# CHECK: error: invalid operand for instruction + bne $t0, ($t0), 1 +# CHECK: error: invalid operand for instruction + beq $t0, ($t0), 1 + + # Check for errors when using conditional branch pseudos after .set noat. .set noat local_label: diff --git a/llvm/test/MC/RISCV/Relocations/mc-dump.s b/llvm/test/MC/RISCV/Relocations/mc-dump.s index 24f3e67ebbdda..c646e6f54b261 100644 --- a/llvm/test/MC/RISCV/Relocations/mc-dump.s +++ b/llvm/test/MC/RISCV/Relocations/mc-dump.s @@ -2,12 +2,12 @@ # RUN: llvm-mc -filetype=obj --triple=riscv64 --mattr=+relax %s -debug-only=mc-dump -o /dev/null 2>&1 | FileCheck %s # CHECK:Sections:[ -# CHECK-NEXT:MCSection Name:.text +# CHECK-NEXT:MCSection Name:.text LinkerRelaxable # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 .text # CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops # CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00] -# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 +# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 LinkerRelaxable # CHECK-NEXT: Symbol @0 $x # CHECK-NEXT:8 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops # CHECK-NEXT:12 Data Size:4 [13,05,30,00] diff --git a/llvm/test/MC/RISCV/xqcibi-linker-relaxation.s b/llvm/test/MC/RISCV/xqcibi-linker-relaxation.s new file mode 100644 index 0000000000000..b12585265bf1d --- /dev/null +++ b/llvm/test/MC/RISCV/xqcibi-linker-relaxation.s @@ -0,0 +1,84 @@ +# RUN: llvm-mc --triple=riscv32 -mattr=+relax,+experimental-xqcilb,+experimental-xqcibi \ +# RUN: %s -filetype=obj -o - -riscv-add-build-attributes \ +# RUN: | llvm-objdump -dr -M no-aliases - \ +# RUN: | FileCheck %s + +## This tests that we correctly emit relocations for linker relaxation when +## relaxing `JAL` to `QC.E.JAL`. + +## PR150071 + +.global foo + +# CHECK-LABEL: : +branch_over_relaxable: + jal x1, foo +# CHECK: qc.e.jal 0x0 +# CHECK-NEXT: R_RISCV_VENDOR QUALCOMM +# CHECK-NEXT: R_RISCV_CUSTOM195 foo +# CHECK-NEXT: R_RISCV_RELAX *ABS* + bne a0, a1, branch_over_relaxable +# CHECK-NEXT: bne a0, a1, 0x6 +# CHECK-NEXT: R_RISCV_BRANCH branch_over_relaxable +# CHECK-NOT: R_RISCV_RELAX + qc.e.bnei a0, 0x21, branch_over_relaxable +# CHECK-NEXT: qc.e.bnei a0, 0x21, 0xa +# CHECK-NEXT: R_RISCV_VENDOR QUALCOMM +# CHECK-NEXT: R_RISCV_CUSTOM193 branch_over_relaxable +# CHECK-NOT: R_RISCV_RELAX + ret +# CHECK-NEXT: c.jr ra + +# CHECK-LABEL: : +short_jump_over_fixed: + nop +# CHECK: c.nop + j short_jump_over_fixed +# CHECK-NEXT: c.j 0x14 +# CHECK-NEXT: R_RISCV_RVC_JUMP short_jump_over_fixed +# CHECK-NOT: R_RISCV_RELAX + ret +# CHECK-NEXT: c.jr ra + +# CHECK-LABEL: : +short_jump_over_relaxable: + call foo +# CHECK: auipc ra, 0x0 +# CHECK-NEXT: R_RISCV_CALL_PLT foo +# CHECK-NEXT: R_RISCV_RELAX *ABS* +# CHECK-NEXT: jalr ra, 0x0(ra) + j short_jump_over_relaxable +# CHECK-NEXT: c.j 0x20 +# CHECK-NEXT: R_RISCV_RVC_JUMP short_jump_over_relaxable +# CHECK-NOT: R_RISCV_RELAX + ret +# CHECK-NEXT: c.jr ra + +# CHECK-LABEL: : +mid_jump_over_fixed: + nop +# CHECK: c.nop + .space 0x1000 +# CHECK-NEXT: ... + j mid_jump_over_fixed +# CHECK-NEXT: jal zero, 0x1026 +# CHECK-NEXT: R_RISCV_JAL mid_jump_over_fixed +# CHECK-NOT: R_RISCV_RELAX + ret +# CHECK-NEXT: c.jr ra + +# CHECK-LABEL: : +mid_jump_over_relaxable: + call foo +# CHECK: auipc ra, 0x0 +# CHECK-NEXT: R_RISCV_CALL_PLT foo +# CHECK-NEXT: R_RISCV_RELAX *ABS* +# CHECK-NEXT: jalr ra, 0x0(ra) + .space 0x1000 +# CHECK-NEXT: ... + j mid_jump_over_relaxable +# CHECK-NEXT: jal zero, 0x2034 +# CHECK-NEXT: R_RISCV_JAL mid_jump_over_relaxable +# CHECK-NOT: R_RISCV_RELAX + ret +# CHECK-NEXT: c.jr ra diff --git a/llvm/test/MC/X86/intel-syntax-parentheses.s b/llvm/test/MC/X86/intel-syntax-parentheses.s new file mode 100644 index 0000000000000..ae53f64089070 --- /dev/null +++ b/llvm/test/MC/X86/intel-syntax-parentheses.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s + +.intel_syntax + +// CHECK: error: invalid base+index expression + lea rdi, [(label + rsi) + rip] +// CHECK: leaq 1(%rax,%rdi), %rdi + lea rdi, [(rax + rdi) + 1] +label: + .quad 42 diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/fold-loop-of-urem.ll b/llvm/test/Transforms/CodeGenPrepare/X86/fold-loop-of-urem.ll index 7abc32e4f1cd8..f53127f015391 100644 --- a/llvm/test/Transforms/CodeGenPrepare/X86/fold-loop-of-urem.ll +++ b/llvm/test/Transforms/CodeGenPrepare/X86/fold-loop-of-urem.ll @@ -1065,3 +1065,37 @@ for.body: %exitcond.not = icmp eq i32 %inc, %N br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } + +define i64 @pr150611_add_offset_is_not_loop_invariant(i1 %cond) { +; CHECK-LABEL: define i64 @pr150611_add_offset_is_not_loop_invariant( +; CHECK-SAME: i1 [[COND:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[REMAMT:%.*]] = select i1 [[COND]], i64 2, i64 0 +; CHECK-NEXT: br label %[[FOR_BODY:.*]] +; CHECK: [[FOR_BODY]]: +; CHECK-NEXT: [[INDVARS:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDVARS_NEXT:%.*]], %[[FOR_BODY]] ] +; CHECK-NEXT: [[ADD_OFFSET:%.*]] = zext i1 [[COND]] to i64 +; CHECK-NEXT: [[ADD:%.*]] = add nuw i64 [[INDVARS]], [[ADD_OFFSET]] +; CHECK-NEXT: [[REM:%.*]] = urem i64 [[ADD]], [[REMAMT]] +; CHECK-NEXT: [[INDVARS_NEXT]] = add nuw i64 [[INDVARS]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_NEXT]], 3 +; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_EXIT:.*]], label %[[FOR_BODY]] +; CHECK: [[FOR_EXIT]]: +; CHECK-NEXT: ret i64 [[REM]] +; +entry: + %remamt = select i1 %cond, i64 2, i64 0 + br label %for.body + +for.body: + %indvars = phi i64 [ 0, %entry ], [ %indvars.next, %for.body ] + %add.offset = zext i1 %cond to i64 + %add = add nuw i64 %indvars, %add.offset + %rem = urem i64 %add, %remamt + %indvars.next = add nuw i64 %indvars, 1 + %exitcond = icmp eq i64 %indvars.next, 3 + br i1 %exitcond, label %for.exit, label %for.body + +for.exit: + ret i64 %rem +} diff --git a/llvm/test/Transforms/DeadStoreElimination/zeroed-missing.ll b/llvm/test/Transforms/DeadStoreElimination/zeroed-missing.ll index e390d4bdca632..303afc207c023 100644 --- a/llvm/test/Transforms/DeadStoreElimination/zeroed-missing.ll +++ b/llvm/test/Transforms/DeadStoreElimination/zeroed-missing.ll @@ -12,6 +12,6 @@ define ptr @undeclared_customalloc(i64 %size, i64 %align) { ret ptr %call } -declare ptr @customalloc2(i64, i64) allockind("alloc") "alloc-family"="customalloc2" "alloc-variant-zeroed"="customalloc2_zeroed" +declare ptr @customalloc2(i64, i64) allockind("alloc,uninitialized") "alloc-family"="customalloc2" "alloc-variant-zeroed"="customalloc2_zeroed" ; CHECK-DAG: declare ptr @customalloc2_zeroed(i64, i64) #[[CA2ATTR:[0-9]+]] ; CHECK-DAG: attributes #[[CA2ATTR]] = { allockind("alloc,zeroed") "alloc-family"="customalloc2" } diff --git a/llvm/test/Transforms/GVN/cond_br.ll b/llvm/test/Transforms/GVN/cond_br.ll index 19166d17a8320..fb84b626c7455 100644 --- a/llvm/test/Transforms/GVN/cond_br.ll +++ b/llvm/test/Transforms/GVN/cond_br.ll @@ -53,3 +53,22 @@ if.end: ; preds = %if.else, %if.then } declare void @bar(i32) + +define void @indirectbr_could_not_split() { +; CHECK-LABEL: define void @indirectbr_could_not_split() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: br i1 false, label %[[IBR:.*]], label %[[EXIT:.*]] +; CHECK: [[IBR]]: +; CHECK-NEXT: indirectbr ptr null, [label %[[EXIT]], label %exit] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +entry: + br i1 false, label %ibr, label %exit + +ibr: + indirectbr ptr null, [label %exit, label %exit] + +exit: + ret void +} diff --git a/llvm/test/Transforms/Inline/SystemZ/inline-target-attr.ll b/llvm/test/Transforms/Inline/SystemZ/inline-target-attr.ll index b5c4f42655bb4..71b463b2d2b00 100644 --- a/llvm/test/Transforms/Inline/SystemZ/inline-target-attr.ll +++ b/llvm/test/Transforms/Inline/SystemZ/inline-target-attr.ll @@ -12,28 +12,28 @@ entry: declare i32 @baz(...) #0 -define i32 @bar() #1 { +define i32 @features_subset() #1 { entry: %call = call i32 @foo() ret i32 %call -; CHECK-LABEL: bar -; CHECK: call i32 @foo() +; CHECK-LABEL: features_subset +; CHECK: call i32 (...) @baz() } -define i32 @qux() #0 { +define i32 @features_equal() #0 { entry: %call = call i32 @foo() ret i32 %call -; CHECK-LABEL: qux +; CHECK-LABEL: features_equal ; CHECK: call i32 (...) @baz() } -define i32 @quux() #2 { +define i32 @features_different() #2 { entry: - %call = call i32 @bar() + %call = call i32 @foo() ret i32 %call -; CHECK-LABEL: quux -; CHECK: call i32 @bar() +; CHECK-LABEL: features_different +; CHECK: call i32 @foo() } diff --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll index ab4448b460bfc..820fff433e9e0 100644 --- a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -213,7 +213,7 @@ define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) { define float @fmul_ninf_nnan_mul_zero_nsz(float nofpclass(inf nan) %f) { ; CHECK-LABEL: @fmul_ninf_nnan_mul_zero_nsz( -; CHECK-NEXT: ret float 0.000000e+00 +; CHECK-NEXT: ret float 0.000000e+00 ; %r = fmul nsz float %f, 0.0 ret float %r @@ -221,7 +221,7 @@ define float @fmul_ninf_nnan_mul_zero_nsz(float nofpclass(inf nan) %f) { define float @fmul_ninf_nnan_mul_nzero_nsz(float nofpclass(inf nan) %f) { ; CHECK-LABEL: @fmul_ninf_nnan_mul_nzero_nsz( -; CHECK-NEXT: ret float 0.000000e+00 +; CHECK-NEXT: ret float 0.000000e+00 ; %r = fmul nsz float %f, -0.0 ret float %r @@ -1255,3 +1255,20 @@ define i1 @fptrunc_round_unknown_positive(double %unknown) { %cmp = fcmp nnan oge float %op, 0.0 ret i1 %cmp } + +define half @fabs_select_fabs(half noundef %x) { +; CHECK-LABEL: @fabs_select_fabs( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ABS1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt half [[ABS1]], 0xH0000 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], half [[X]], half 0xH0000 +; CHECK-NEXT: [[ABS2:%.*]] = call half @llvm.fabs.f16(half [[SEL]]) +; CHECK-NEXT: ret half [[ABS2]] +; +entry: + %abs1 = call half @llvm.fabs.f16(half %x) + %cmp = fcmp ogt half %abs1, 0xH0000 + %sel = select i1 %cmp, half %x, half 0xH0000 + %abs2 = call half @llvm.fabs.f16(half %sel) + ret half %abs2 +} diff --git a/llvm/test/Transforms/LoopDistribute/scev-inserted-runtime-check.ll b/llvm/test/Transforms/LoopDistribute/scev-inserted-runtime-check.ll index 98b89abfeafda..057a60918ecf3 100644 --- a/llvm/test/Transforms/LoopDistribute/scev-inserted-runtime-check.ll +++ b/llvm/test/Transforms/LoopDistribute/scev-inserted-runtime-check.ll @@ -10,8 +10,13 @@ define void @f(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d, p ; CHECK-NEXT: br label [[FOR_BODY_LVER_CHECK:%.*]] ; CHECK: for.body.lver.check: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP0]] to i32 +; CHECK-NEXT: [[MUL1:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[TMP2]]) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i32, i1 } [[MUL1]], 0 +; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[MUL1]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], 4294967295 -; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH_LDIST1:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = or i1 [[MUL_OVERFLOW]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP3]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH_LDIST1:%.*]] ; CHECK: for.body.ph.lver.orig: ; CHECK-NEXT: br label [[FOR_BODY_LVER_ORIG:%.*]] ; CHECK: for.body.lver.orig: @@ -75,7 +80,7 @@ define void @f(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d, p ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT2:%.*]], label [[FOR_BODY]] ; CHECK: for.end.loopexit: ; CHECK-NEXT: br label [[FOR_END:%.*]] -; CHECK: for.end.loopexit1: +; CHECK: for.end.loopexit2: ; CHECK-NEXT: br label [[FOR_END]] ; CHECK: for.end: ; CHECK-NEXT: ret void @@ -135,8 +140,13 @@ define void @f_with_offset(ptr noalias %b, ptr noalias %c, ptr noalias %d, ptr n ; CHECK-NEXT: br label [[FOR_BODY_LVER_CHECK:%.*]] ; CHECK: for.body.lver.check: ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP0]] to i32 +; CHECK-NEXT: [[MUL1:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[TMP2]]) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i32, i1 } [[MUL1]], 0 +; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i32, i1 } [[MUL1]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], 4294967295 -; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH_LDIST1:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = or i1 [[MUL_OVERFLOW]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP3]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH_LDIST1:%.*]] ; CHECK: for.body.ph.lver.orig: ; CHECK-NEXT: br label [[FOR_BODY_LVER_ORIG:%.*]] ; CHECK: for.body.lver.orig: @@ -200,7 +210,7 @@ define void @f_with_offset(ptr noalias %b, ptr noalias %c, ptr noalias %d, ptr n ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT2:%.*]], label [[FOR_BODY]] ; CHECK: for.end.loopexit: ; CHECK-NEXT: br label [[FOR_END:%.*]] -; CHECK: for.end.loopexit1: +; CHECK: for.end.loopexit2: ; CHECK-NEXT: br label [[FOR_END]] ; CHECK: for.end: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll b/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll new file mode 100644 index 0000000000000..dd524ab7d140d --- /dev/null +++ b/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require,loop(loop-simplifycfg)' -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s + +define void @test(ptr %addr) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr [[ADDR:%.*]]) { +; CHECK-NEXT: indirectbr ptr [[ADDR]], [label %[[A:.*]], label %C] +; CHECK: [[A]]: +; CHECK-NEXT: br i1 true, label %[[B:.*]], label %[[C_LOOPEXIT:.*]] +; CHECK: [[B]]: +; CHECK-NEXT: br i1 true, label %[[A]], label %[[C_LOOPEXIT]] +; CHECK: [[C_LOOPEXIT]]: +; CHECK-NEXT: br label %[[C:.*]] +; CHECK: [[C]]: +; CHECK-NEXT: unreachable +; + + indirectbr ptr %addr, [label %A, label %C] + +A: + br i1 true, label %B, label %C + +B: + br i1 true, label %A, label %C + +C: + unreachable +} diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/fmax-without-fast-math-flags.ll b/llvm/test/Transforms/LoopVectorize/AArch64/fmax-without-fast-math-flags.ll index 451574a258c2b..427a05cc1c843 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/fmax-without-fast-math-flags.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/fmax-without-fast-math-flags.ll @@ -42,18 +42,59 @@ define float @fmaxnum(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fmaxnum( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP7:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP8:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 4 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP7]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VEC_PHI]], <4 x float> [[WIDE_LOAD]]) +; CHECK-NEXT: [[TMP8]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VEC_PHI1]], <4 x float> [[WIDE_LOAD2]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 8 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP4:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD2]], [[WIDE_LOAD2]] +; CHECK-NEXT: [[TMP5:%.*]] = or <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP6]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP6]], [[TMP9]] +; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP7]] +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI1]], <4 x float> [[TMP8]] +; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP6]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]]) +; CHECK-NEXT: [[TMP13:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[RDX_MINMAX_SELECT]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP15:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP15]], i32 0 +; CHECK-NEXT: [[TMP17:%.*]] = and i1 [[CMP_N]], [[TMP16]] +; CHECK-NEXT: br i1 [[TMP17]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP14]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP13]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[MAX]], float [[L]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP13]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/fmin-without-fast-math-flags.ll b/llvm/test/Transforms/LoopVectorize/AArch64/fmin-without-fast-math-flags.ll index e93ee5563b057..1a8e5940d88e7 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/fmin-without-fast-math-flags.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/fmin-without-fast-math-flags.ll @@ -42,18 +42,59 @@ define float @fminnum(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fminnum( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP7:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP8:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 4 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP7]] = call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VEC_PHI]], <4 x float> [[WIDE_LOAD]]) +; CHECK-NEXT: [[TMP8]] = call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VEC_PHI1]], <4 x float> [[WIDE_LOAD2]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 8 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP4:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD2]], [[WIDE_LOAD2]] +; CHECK-NEXT: [[TMP5:%.*]] = or <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP6]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP6]], [[TMP9]] +; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP7]] +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI1]], <4 x float> [[TMP8]] +; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP6]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = call <4 x float> @llvm.minnum.v4f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]]) +; CHECK-NEXT: [[TMP13:%.*]] = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> [[RDX_MINMAX_SELECT]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP15:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP15]], i32 0 +; CHECK-NEXT: [[TMP17:%.*]] = and i1 [[CMP_N]], [[TMP16]] +; CHECK-NEXT: br i1 [[TMP17]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP14]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP13]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.minnum.f32(float [[MAX]], float [[L]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP13]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory-with-wide-ops.ll b/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory-with-wide-ops.ll index 813d61b52100f..aec6c0be6dde2 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory-with-wide-ops.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory-with-wide-ops.ll @@ -1203,3 +1203,82 @@ loop: exit: ret void } + +; Make sure multiple uses of a narrowed op are handled correctly, +; https://github.com/llvm/llvm-project/issues/156190. +define void @multiple_store_groups_storing_same_wide_bin_op(ptr noalias %A, ptr noalias %B, ptr noalias %C) { +; VF2-LABEL: define void @multiple_store_groups_storing_same_wide_bin_op( +; VF2-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { +; VF2-NEXT: [[ENTRY:.*:]] +; VF2-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; VF2: [[VECTOR_PH]]: +; VF2-NEXT: br label %[[VECTOR_BODY:.*]] +; VF2: [[VECTOR_BODY]]: +; VF2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; VF2-NEXT: [[TMP0:%.*]] = getelementptr { double, double }, ptr [[A]], i64 [[INDEX]] +; VF2-NEXT: [[BROADCAST_SPLAT:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; VF2-NEXT: [[TMP2:%.*]] = fadd contract <2 x double> [[BROADCAST_SPLAT]], splat (double 2.000000e+01) +; VF2-NEXT: [[TMP3:%.*]] = getelementptr { double, double }, ptr [[B]], i64 [[INDEX]] +; VF2-NEXT: store <2 x double> [[TMP2]], ptr [[TMP3]], align 8 +; VF2-NEXT: [[TMP4:%.*]] = getelementptr { double, double }, ptr [[C]], i64 [[INDEX]] +; VF2-NEXT: store <2 x double> [[TMP2]], ptr [[TMP4]], align 8 +; VF2-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 1 +; VF2-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000 +; VF2-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP30:![0-9]+]] +; VF2: [[MIDDLE_BLOCK]]: +; VF2-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]] +; VF2: [[SCALAR_PH]]: +; +; VF4-LABEL: define void @multiple_store_groups_storing_same_wide_bin_op( +; VF4-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { +; VF4-NEXT: [[ENTRY:.*:]] +; VF4-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; VF4: [[VECTOR_PH]]: +; VF4-NEXT: br label %[[VECTOR_BODY:.*]] +; VF4: [[VECTOR_BODY]]: +; VF4-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; VF4-NEXT: [[TMP0:%.*]] = getelementptr { double, double }, ptr [[A]], i64 [[INDEX]] +; VF4-NEXT: [[WIDE_VEC:%.*]] = load <8 x double>, ptr [[TMP0]], align 8 +; VF4-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <8 x double> [[WIDE_VEC]], <8 x double> poison, <4 x i32> +; VF4-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <8 x double> [[WIDE_VEC]], <8 x double> poison, <4 x i32> +; VF4-NEXT: [[TMP1:%.*]] = fadd contract <4 x double> [[STRIDED_VEC]], splat (double 2.000000e+01) +; VF4-NEXT: [[TMP2:%.*]] = fadd contract <4 x double> [[STRIDED_VEC1]], splat (double 2.000000e+01) +; VF4-NEXT: [[TMP3:%.*]] = getelementptr { double, double }, ptr [[B]], i64 [[INDEX]] +; VF4-NEXT: [[TMP4:%.*]] = shufflevector <4 x double> [[TMP1]], <4 x double> [[TMP2]], <8 x i32> +; VF4-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <8 x double> [[TMP4]], <8 x double> poison, <8 x i32> +; VF4-NEXT: store <8 x double> [[INTERLEAVED_VEC]], ptr [[TMP3]], align 8 +; VF4-NEXT: [[TMP5:%.*]] = getelementptr { double, double }, ptr [[C]], i64 [[INDEX]] +; VF4-NEXT: store <8 x double> [[INTERLEAVED_VEC]], ptr [[TMP5]], align 8 +; VF4-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; VF4-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000 +; VF4-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP30:![0-9]+]] +; VF4: [[MIDDLE_BLOCK]]: +; VF4-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]] +; VF4: [[SCALAR_PH]]: +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %gep.A = getelementptr { double, double }, ptr %A, i64 %iv + %l.A.0 = load double, ptr %gep.A, align 8 + %gep.A.1 = getelementptr inbounds nuw i8, ptr %gep.A, i64 8 + %l.A.1 = load double, ptr %gep.A.1, align 8 + %add.0 = fadd contract double %l.A.0, 20.0 + %add.1 = fadd contract double %l.A.1, 20.0 + %gep.B = getelementptr { double, double }, ptr %B, i64 %iv + store double %add.0, ptr %gep.B, align 8 + %gep.B.1 = getelementptr inbounds nuw i8, ptr %gep.B, i64 8 + store double %add.1, ptr %gep.B.1, align 8 + %gep.C = getelementptr { double, double }, ptr %C, i64 %iv + %gep.C.1 = getelementptr inbounds nuw i8, ptr %gep.C, i64 8 + store double %add.0, ptr %gep.C, align 8 + store double %add.1, ptr %gep.C.1, align 8 + %iv.next = add nuw nsw i64 %iv, 1 + %.not = icmp eq i64 %iv.next, 1000 + br i1 %.not, label %exit, label %loop + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory.ll b/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory.ll index 6acd7989dbfd2..451cbd7601a85 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/transform-narrow-interleave-to-widen-memory.ll @@ -587,3 +587,76 @@ loop: exit: ret void } + +define void @multiple_store_groups_storing_same_load_group(ptr noalias %A, ptr noalias %B, ptr noalias %C) { +; VF2-LABEL: define void @multiple_store_groups_storing_same_load_group( +; VF2-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { +; VF2-NEXT: [[ENTRY:.*:]] +; VF2-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; VF2: [[VECTOR_PH]]: +; VF2-NEXT: br label %[[VECTOR_BODY:.*]] +; VF2: [[VECTOR_BODY]]: +; VF2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; VF2-NEXT: [[TMP0:%.*]] = getelementptr { double, double }, ptr [[A]], i64 [[INDEX]] +; VF2-NEXT: [[WIDE_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; VF2-NEXT: [[WIDE_LOAD1:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; VF2-NEXT: [[TMP1:%.*]] = getelementptr { double, double }, ptr [[B]], i64 [[INDEX]] +; VF2-NEXT: store <2 x double> [[WIDE_LOAD]], ptr [[TMP1]], align 8 +; VF2-NEXT: [[TMP2:%.*]] = getelementptr { double, double }, ptr [[C]], i64 [[INDEX]] +; VF2-NEXT: store <2 x double> [[WIDE_LOAD1]], ptr [[TMP2]], align 8 +; VF2-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 1 +; VF2-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000 +; VF2-NEXT: br i1 [[TMP3]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]] +; VF2: [[MIDDLE_BLOCK]]: +; VF2-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]] +; VF2: [[SCALAR_PH]]: +; +; VF4-LABEL: define void @multiple_store_groups_storing_same_load_group( +; VF4-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) { +; VF4-NEXT: [[ENTRY:.*:]] +; VF4-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; VF4: [[VECTOR_PH]]: +; VF4-NEXT: br label %[[VECTOR_BODY:.*]] +; VF4: [[VECTOR_BODY]]: +; VF4-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; VF4-NEXT: [[TMP0:%.*]] = getelementptr { double, double }, ptr [[A]], i64 [[INDEX]] +; VF4-NEXT: [[WIDE_VEC:%.*]] = load <8 x double>, ptr [[TMP0]], align 8 +; VF4-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <8 x double> [[WIDE_VEC]], <8 x double> poison, <4 x i32> +; VF4-NEXT: [[STRIDED_VEC1:%.*]] = shufflevector <8 x double> [[WIDE_VEC]], <8 x double> poison, <4 x i32> +; VF4-NEXT: [[TMP1:%.*]] = getelementptr { double, double }, ptr [[B]], i64 [[INDEX]] +; VF4-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[STRIDED_VEC]], <4 x double> [[STRIDED_VEC1]], <8 x i32> +; VF4-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <8 x double> [[TMP2]], <8 x double> poison, <8 x i32> +; VF4-NEXT: store <8 x double> [[INTERLEAVED_VEC]], ptr [[TMP1]], align 8 +; VF4-NEXT: [[TMP3:%.*]] = getelementptr { double, double }, ptr [[C]], i64 [[INDEX]] +; VF4-NEXT: store <8 x double> [[INTERLEAVED_VEC]], ptr [[TMP3]], align 8 +; VF4-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; VF4-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000 +; VF4-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]] +; VF4: [[MIDDLE_BLOCK]]: +; VF4-NEXT: br i1 true, [[EXIT:label %.*]], label %[[SCALAR_PH]] +; VF4: [[SCALAR_PH]]: +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %gep.A = getelementptr { double, double }, ptr %A, i64 %iv + %gep.A.1 = getelementptr inbounds nuw i8, ptr %gep.A, i64 8 + %l.A.0 = load double, ptr %gep.A, align 8 + %l.A.1 = load double, ptr %gep.A.1, align 8 + %gep.B = getelementptr { double, double }, ptr %B, i64 %iv + %gep.B.1 = getelementptr inbounds nuw i8, ptr %gep.B, i64 8 + store double %l.A.0, ptr %gep.B, align 8 + store double %l.A.1, ptr %gep.B.1, align 8 + %gep.C = getelementptr { double, double }, ptr %C, i64 %iv + %gep.C.1 = getelementptr inbounds nuw i8, ptr %gep.C, i64 8 + store double %l.A.0, ptr %gep.C, align 8 + store double %l.A.1, ptr %gep.C.1, align 8 + %iv.next = add nuw nsw i64 %iv, 1 + %.not = icmp eq i64 %iv.next, 1000 + br i1 %.not, label %exit, label %loop + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll index 147e949808b54..c1566c4dd32bf 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/cost-model.ll @@ -1045,8 +1045,8 @@ define i64 @live_in_known_1_via_scev() { ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_PHI]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[INDEX_NEXT]], 8 -; CHECK-NEXT: br i1 [[TMP2]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[INDEX_NEXT]], 8 +; CHECK-NEXT: br i1 [[TMP0]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vector.reduce.mul.v4i64(<4 x i64> [[VEC_PHI]]) ; CHECK-NEXT: br label [[EXIT:%.*]] @@ -1213,6 +1213,7 @@ define i32 @g(i64 %n) { ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP1]], 4 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[VEC_EPILOG_SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]] ; CHECK: vector.scevcheck: +; CHECK-NEXT: [[TMP28:%.*]] = trunc i64 [[N]] to i32 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[N]], 4294967295 ; CHECK-NEXT: br i1 [[TMP2]], label [[VEC_EPILOG_SCALAR_PH]], label [[VECTOR_MAIN_LOOP_ITER_CHECK:%.*]] ; CHECK: vector.main.loop.iter.check: diff --git a/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags-interleave.ll b/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags-interleave.ll index b2e080fef2e57..a2eddad179216 100644 --- a/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags-interleave.ll +++ b/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags-interleave.ll @@ -42,18 +42,59 @@ define float @fmaxnum(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fmaxnum( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP7:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP8:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 4 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP7]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VEC_PHI]], <4 x float> [[WIDE_LOAD]]) +; CHECK-NEXT: [[TMP8]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VEC_PHI1]], <4 x float> [[WIDE_LOAD2]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 8 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP3:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP4:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD2]], [[WIDE_LOAD2]] +; CHECK-NEXT: [[TMP5:%.*]] = or <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP6]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[TMP6]], [[TMP9]] +; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP7]] +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI1]], <4 x float> [[TMP8]] +; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP6]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[RDX_MINMAX_SELECT:%.*]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[TMP11]], <4 x float> [[TMP12]]) +; CHECK-NEXT: [[TMP13:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[RDX_MINMAX_SELECT]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP15:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP15]], i32 0 +; CHECK-NEXT: [[TMP17:%.*]] = and i1 [[CMP_N]], [[TMP16]] +; CHECK-NEXT: br i1 [[TMP17]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP14]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP13]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[MAX]], float [[L]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP13]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags.ll b/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags.ll index 5661406b88a5a..1ca5586942d7c 100644 --- a/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags.ll +++ b/llvm/test/Transforms/LoopVectorize/fmax-without-fast-math-flags.ll @@ -192,18 +192,51 @@ define float @fmaxnum_1(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fmaxnum_1( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP4:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP4]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[WIDE_LOAD]], <4 x float> [[VEC_PHI]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP2:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP3]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP7:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP3]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[TMP7]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP10]], i32 0 +; CHECK-NEXT: [[TMP12:%.*]] = and i1 [[CMP_N]], [[TMP11]] +; CHECK-NEXT: br i1 [[TMP12]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP8]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[L]], float [[MAX]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP8]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: @@ -227,18 +260,234 @@ define float @fmaxnum_2(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fmaxnum_2( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP4:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP4]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VEC_PHI]], <4 x float> [[WIDE_LOAD]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP2:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP3]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP7:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP3]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[TMP7]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP10]], i32 0 +; CHECK-NEXT: [[TMP12:%.*]] = and i1 [[CMP_N]], [[TMP11]] +; CHECK-NEXT: br i1 [[TMP12]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP8]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 +; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[MAX]], float [[L]]) +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP8]], %[[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] + %max = phi float [ -1.000000e+07, %entry ], [ %max.next, %loop ] + %gep.src = getelementptr inbounds nuw float, ptr %src, i64 %iv + %l = load float, ptr %gep.src, align 4 + %max.next = call float @llvm.maxnum.f32(float %max, float %l) + %iv.next = add nuw nsw i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %n + br i1 %ec, label %exit, label %loop + +exit: + ret float %max.next +} + +define float @fmaxnum_induction_starts_at_10(ptr %src, i64 %n) { +; CHECK-LABEL: define float @fmaxnum_induction_starts_at_10( +; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -10 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]] +; 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> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP3:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[IV:%.*]] = add i64 10, [[INDEX]] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[WIDE_LOAD]], <4 x float> [[VEC_PHI]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP6]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = or i1 [[TMP6]], [[TMP4]] +; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP3]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP6]], i64 [[INDEX]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[TMP8]]) +; CHECK-NEXT: [[TMP11:%.*]] = add i64 10, [[TMP9]] +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]] +; CHECK-NEXT: [[TMP12:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP12]], i32 0 +; CHECK-NEXT: [[TMP14:%.*]] = and i1 [[CMP_N]], [[TMP13]] +; CHECK-NEXT: br i1 [[TMP14]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP11]], %[[MIDDLE_BLOCK]] ], [ 10, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP10]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 +; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[L]], float [[MAX]]) +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP10]], %[[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] +; +entry: + br label %loop + +loop: + %iv = phi i64 [ 10, %entry ], [ %iv.next, %loop ] + %max = phi float [ -1.000000e+07, %entry ], [ %max.next, %loop ] + %gep.src = getelementptr inbounds nuw float, ptr %src, i64 %iv + %l = load float, ptr %gep.src, align 4 + %max.next = call float @llvm.maxnum.f32(float %l, float %max) + %iv.next = add nuw nsw i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %n + br i1 %ec, label %exit, label %loop + +exit: + ret float %max.next +} + +define float @fmaxnum_induction_starts_at_value(ptr %src, i64 %start, i64 %n) { +; CHECK-LABEL: define float @fmaxnum_induction_starts_at_value( +; CHECK-SAME: ptr [[SRC:%.*]], i64 [[START:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[TMP0:%.*]] = sub i64 [[N]], [[START]] +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]] +; 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> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP3:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[IV:%.*]] = add i64 [[START]], [[INDEX]] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3]] = call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[WIDE_LOAD]], <4 x float> [[VEC_PHI]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP5:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP5]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP6]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = or i1 [[TMP6]], [[TMP4]] +; CHECK-NEXT: br i1 [[TMP7]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP8:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP3]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP6]], i64 [[INDEX]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> [[TMP8]]) +; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[START]], [[TMP9]] +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]] +; CHECK-NEXT: [[TMP12:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP12]], i32 0 +; CHECK-NEXT: [[TMP14:%.*]] = and i1 [[CMP_N]], [[TMP13]] +; CHECK-NEXT: br i1 [[TMP14]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP11]], %[[MIDDLE_BLOCK]] ], [ [[START]], %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP10]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 +; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[L]], float [[MAX]]) +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP10]], %[[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] +; +entry: + br label %loop + +loop: + %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ] + %max = phi float [ -1.000000e+07, %entry ], [ %max.next, %loop ] + %gep.src = getelementptr inbounds nuw float, ptr %src, i64 %iv + %l = load float, ptr %gep.src, align 4 + %max.next = call float @llvm.maxnum.f32(float %l, float %max) + %iv.next = add nuw nsw i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %n + br i1 %ec, label %exit, label %loop + +exit: + ret float %max.next +} + +define float @fmaxnum_with_additional_add(ptr noalias %src, ptr noalias %src.2, i64 %n) { +; CHECK-LABEL: define float @fmaxnum_with_additional_add( +; CHECK-SAME: ptr noalias [[SRC:%.*]], ptr noalias [[SRC_2:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[SUM_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr inbounds nuw i32, ptr [[SRC_2]], i64 [[IV]] +; CHECK-NEXT: [[L_SRC_2:%.*]] = load i32, ptr [[GEP_SRC_2]], align 4 +; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[L_SRC_2]] ; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] ; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 -; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[MAX]], float [[L]]) +; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.maxnum.f32(float [[L]], float [[MAX]]) ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] ; CHECK: [[EXIT]]: +; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], %[[LOOP]] ] ; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: store i32 [[SUM_NEXT_LCSSA]], ptr [[SRC_2]], align 4 ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: @@ -247,14 +496,19 @@ entry: loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %max = phi float [ -1.000000e+07, %entry ], [ %max.next, %loop ] + %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop ] + %gep.src.2 = getelementptr inbounds nuw i32, ptr %src.2, i64 %iv + %l.src.2 = load i32, ptr %gep.src.2, align 4 + %sum.next = add i32 %sum, %l.src.2 %gep.src = getelementptr inbounds nuw float, ptr %src, i64 %iv %l = load float, ptr %gep.src, align 4 - %max.next = call float @llvm.maxnum.f32(float %max, float %l) + %max.next = call float @llvm.maxnum.f32(float %l, float %max) %iv.next = add nuw nsw i64 %iv, 1 %ec = icmp eq i64 %iv.next, %n br i1 %ec, label %exit, label %loop exit: + store i32 %sum.next, ptr %src.2 ret float %max.next } diff --git a/llvm/test/Transforms/LoopVectorize/fmin-without-fast-math-flags.ll b/llvm/test/Transforms/LoopVectorize/fmin-without-fast-math-flags.ll index 148beb64a3609..68bc8d0640a3f 100644 --- a/llvm/test/Transforms/LoopVectorize/fmin-without-fast-math-flags.ll +++ b/llvm/test/Transforms/LoopVectorize/fmin-without-fast-math-flags.ll @@ -192,18 +192,51 @@ define float @fminnum_1(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fminnum_1( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP4:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP4]] = call <4 x float> @llvm.minnum.v4f32(<4 x float> [[WIDE_LOAD]], <4 x float> [[VEC_PHI]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP2:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP3]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP7:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP3]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> [[TMP7]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP10]], i32 0 +; CHECK-NEXT: [[TMP12:%.*]] = and i1 [[CMP_N]], [[TMP11]] +; CHECK-NEXT: br i1 [[TMP12]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP8]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.minnum.f32(float [[L]], float [[MAX]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP8]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: @@ -227,18 +260,51 @@ define float @fminnum_2(ptr %src, i64 %n) { ; CHECK-LABEL: define float @fminnum_2( ; CHECK-SAME: ptr [[SRC:%.*]], i64 [[N:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ splat (float -1.000000e+07), %[[VECTOR_PH]] ], [ [[TMP4:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw float, ptr [[GEP_SRC]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP4]] = call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VEC_PHI]], <4 x float> [[WIDE_LOAD]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[IV]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: [[TMP2:%.*]] = fcmp uno <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP2]]) +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[TMP3]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i1> [[BROADCAST_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP3]], [[TMP5]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: [[TMP7:%.*]] = select <4 x i1> [[BROADCAST_SPLAT]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP3]], i64 [[IV]], i64 [[N_VEC]] +; CHECK-NEXT: [[TMP8:%.*]] = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> [[TMP7]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[BROADCAST_SPLAT]], splat (i1 true) +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP10]], i32 0 +; CHECK-NEXT: [[TMP12:%.*]] = and i1 [[CMP_N]], [[TMP11]] +; CHECK-NEXT: br i1 [[TMP12]], label %[[EXIT:.*]], label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP8]], %[[MIDDLE_BLOCK]] ], [ -1.000000e+07, %[[ENTRY]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[MAX:%.*]] = phi float [ -1.000000e+07, %[[ENTRY]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[GEP_SRC:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV]] -; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC]], align 4 +; CHECK-NEXT: [[IV1:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX:%.*]] = phi float [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[MAX_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[GEP_SRC1:%.*]] = getelementptr inbounds nuw float, ptr [[SRC]], i64 [[IV1]] +; CHECK-NEXT: [[L:%.*]] = load float, ptr [[GEP_SRC1]], align 4 ; CHECK-NEXT: [[MAX_NEXT]] = call float @llvm.minnum.f32(float [[MAX]], float [[L]]) -; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV1]], 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] ; CHECK: [[EXIT]]: -; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ] +; CHECK-NEXT: [[MAX_NEXT_LCSSA:%.*]] = phi float [ [[MAX_NEXT]], %[[LOOP]] ], [ [[TMP8]], %[[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[MAX_NEXT_LCSSA]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll deleted file mode 100644 index 661e8eb666d54..0000000000000 --- a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll +++ /dev/null @@ -1,124 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 -; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses=true < %s | FileCheck %s - -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" - -; Check that the interleaved-mem-access analysis currently does not create an -; interleave group for access 'a' due to the possible pointer wrap-around. -; -; To begin with, in this test the candidate interleave group can be created -; only when getPtrStride is called with Assume=true. Next, because -; the interleave-group of the loads is not full (has gaps), we also need to check -; for possible pointer wrapping. Here we currently use Assume=false and as a -; result cannot prove the transformation is safe and therefore invalidate the -; candidate interleave group. -; - -; void func(unsigned * __restrict a, unsigned * __restrict b, unsigned char x, unsigned char y) { -; int i = 0; -; for (unsigned char index = x; i < y; index +=2, ++i) -; b[i] = aptr 2; -; -; } - -define void @_Z4funcPjS_hh(ptr noalias nocapture readonly %a, ptr noalias nocapture %b, i8 zeroext %x, i8 zeroext %y) local_unnamed_addr { -; CHECK-LABEL: define void @_Z4funcPjS_hh( -; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]], ptr noalias captures(none) [[B:%.*]], i8 zeroext [[X:%.*]], i8 zeroext [[Y:%.*]]) local_unnamed_addr { -; CHECK-NEXT: [[ENTRY:.*:]] -; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[Y]], 0 -; CHECK-NEXT: br i1 [[CMP9]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] -; CHECK: [[FOR_BODY_PREHEADER]]: -; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i8 [[Y]] to i64 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i8 [[Y]], 5 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] -; CHECK: [[VECTOR_SCEVCHECK]]: -; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8 -; CHECK-NEXT: [[MUL_RESULT:%.*]] = shl i8 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i8 [[MUL_RESULT]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i64 [[TMP0]], 127 -; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]] -; CHECK-NEXT: br i1 [[TMP5]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] -; CHECK: [[VECTOR_PH]]: -; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[WIDE_TRIP_COUNT]], 3 -; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 -; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP8]], i64 4, i64 [[N_MOD_VF]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[WIDE_TRIP_COUNT]], [[TMP7]] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i64 [[N_VEC]] to i8 -; CHECK-NEXT: [[TMP6:%.*]] = shl i8 [[DOTCAST]], 1 -; CHECK-NEXT: [[IND_END:%.*]] = add i8 [[X]], [[TMP6]] -; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] -; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[DOTCAST3:%.*]] = trunc i64 [[INDEX]] to i8 -; CHECK-NEXT: [[TMP9:%.*]] = shl i8 [[DOTCAST3]], 1 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i8 [[X]], [[TMP9]] -; CHECK-NEXT: [[TMP14:%.*]] = zext i8 [[OFFSET_IDX]] to i64 -; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw i32, ptr [[A]], i64 [[TMP14]] -; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <8 x i32>, ptr [[TMP15]], align 4 -; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <8 x i32> [[WIDE_VEC]], <8 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP24:%.*]] = shl <4 x i32> [[TMP23]], splat (i32 1) -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]] -; CHECK-NEXT: store <4 x i32> [[TMP24]], ptr [[TMP25]], align 4 -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP26]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br label %[[SCALAR_PH]] -; CHECK: [[SCALAR_PH]]: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[FOR_BODY_PREHEADER]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] -; CHECK-NEXT: [[BC_RESUME_VAL3:%.*]] = phi i8 [ [[IND_END]], %[[MIDDLE_BLOCK]] ], [ [[X]], %[[FOR_BODY_PREHEADER]] ], [ [[X]], %[[VECTOR_SCEVCHECK]] ] -; CHECK-NEXT: br label %[[FOR_BODY:.*]] -; CHECK: [[FOR_COND_CLEANUP_LOOPEXIT:.*]]: -; CHECK-NEXT: br label %[[FOR_COND_CLEANUP]] -; CHECK: [[FOR_COND_CLEANUP]]: -; CHECK-NEXT: ret void -; CHECK: [[FOR_BODY]]: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[FOR_BODY]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ] -; CHECK-NEXT: [[INDEX_011:%.*]] = phi i8 [ [[ADD:%.*]], %[[FOR_BODY]] ], [ [[BC_RESUME_VAL3]], %[[SCALAR_PH]] ] -; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[INDEX_011]] to i64 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[A]], i64 [[IDXPROM]] -; CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[TMP27]], 1 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD]] = add i8 [[INDEX_011]], 2 -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] -; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_COND_CLEANUP_LOOPEXIT]], label %[[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] -; -entry: - %cmp9 = icmp eq i8 %y, 0 - br i1 %cmp9, label %for.cond.cleanup, label %for.body.preheader - -for.body.preheader: - %wide.trip.count = zext i8 %y to i64 - br label %for.body - -for.cond.cleanup.loopexit: - br label %for.cond.cleanup - -for.cond.cleanup: - ret void - -for.body: - %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ] - %index.011 = phi i8 [ %add, %for.body ], [ %x, %for.body.preheader ] - %idxprom = zext i8 %index.011 to i64 - %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom - %0 = load i32, ptr %arrayidx, align 4 - %mul = shl i32 %0, 1 - %arrayidx2 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv - store i32 %mul, ptr %arrayidx2, align 4 - %add = add i8 %index.011, 2 - %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 - %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count - br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body -} -;. -; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} -; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} -; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]]} -;. diff --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll new file mode 100644 index 0000000000000..38438941eb357 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll @@ -0,0 +1,258 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5 +; RUN: opt -S -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses=true %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; Check that the interleaved-mem-access analysis currently does not create an +; interleave group for access 'a' due to the possible pointer wrap-around. +; +; To begin with, in this test the candidate interleave group can be created +; only when getPtrStride is called with Assume=true. Next, because +; the interleave-group of the loads is not full (has gaps), we also need to check +; for possible pointer wrapping. Here we currently use Assume=false and as a +; result cannot prove the transformation is safe and therefore invalidate the +; candidate interleave group. +; + +; void func(unsigned * __restrict a, unsigned * __restrict b, unsigned char x, unsigned char y) { +; int i = 0; +; for (unsigned char index = x; i < y; index +=2, ++i) +; b[i] = aptr 2; +; +; } + +define void @wrap_around_scev_check(ptr noalias %a, ptr noalias %b, i8 %x, i8 %y) { +; CHECK-LABEL: define void @wrap_around_scev_check( +; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[Y]], 0 +; CHECK-NEXT: br i1 [[CMP9]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]] +; CHECK: [[LOOP_PREHEADER]]: +; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i8 [[Y]] to i64 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[WIDE_TRIP_COUNT]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] +; CHECK: [[VECTOR_SCEVCHECK]]: +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8 +; CHECK-NEXT: [[MUL1:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 2, i8 [[TMP1]]) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i8, i1 } [[MUL1]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i8, i1 } [[MUL1]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X]], [[MUL_RESULT]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i8 [[TMP2]], [[X]] +; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP17:%.*]] = icmp ugt i64 [[TMP0]], 255 +; CHECK-NEXT: [[TMP18:%.*]] = or i1 [[TMP5]], [[TMP17]] +; CHECK-NEXT: br i1 [[TMP18]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[WIDE_TRIP_COUNT]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[WIDE_TRIP_COUNT]], [[TMP7]] +; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i64 [[N_VEC]] to i8 +; CHECK-NEXT: [[TMP8:%.*]] = mul i8 [[DOTCAST]], 2 +; CHECK-NEXT: [[TMP9:%.*]] = add i8 [[X]], [[TMP8]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[DOTCAST2:%.*]] = trunc i64 [[INDEX]] to i8 +; CHECK-NEXT: [[TMP10:%.*]] = mul i8 [[DOTCAST2]], 2 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i8 [[X]], [[TMP10]] +; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[OFFSET_IDX]] to i64 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <8 x i32>, ptr [[TMP12]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <8 x i32> [[WIDE_VEC]], <8 x i32> poison, <4 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shl <4 x i32> [[STRIDED_VEC]], splat (i32 1) +; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i32 0 +; CHECK-NEXT: store <4 x i32> [[TMP13]], ptr [[TMP19]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[LOOP_PREHEADER]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL3:%.*]] = phi i8 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ [[X]], %[[LOOP_PREHEADER]] ], [ [[X]], %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[INDEX_011:%.*]] = phi i8 [ [[BC_RESUME_VAL3]], %[[SCALAR_PH]] ], [ [[ADD:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[INDEX_011]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]] +; CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[TMP16]], 1 +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]] +; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 4 +; CHECK-NEXT: [[ADD]] = add i8 [[INDEX_011]], 2 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: [[EXIT_LOOPEXIT]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +entry: + %cmp9 = icmp eq i8 %y, 0 + br i1 %cmp9, label %exit, label %loop.preheader + +loop.preheader: + %wide.trip.count = zext i8 %y to i64 + br label %loop + +loop: + %iv = phi i64 [ 0, %loop.preheader ], [ %iv.next, %loop ] + %index.011 = phi i8 [ %x, %loop.preheader ], [ %add, %loop ] + %idxprom = zext i8 %index.011 to i64 + %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom + %0 = load i32, ptr %arrayidx, align 4 + %mul = shl i32 %0, 1 + %arrayidx2 = getelementptr inbounds i32, ptr %b, i64 %iv + store i32 %mul, ptr %arrayidx2, align 4 + %add = add i8 %index.011, 2 + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %iv.next, %wide.trip.count + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; For %gep, we have the following SCEV: ((4 * (zext i4 {0,+,5}<%loop> to i64)) + %x). +; Note the i4 bit wide AddRec {0,+,5}. It is known to wrap in the loop with trip count 16. +define void @wrap_predicate_for_interleave_group_wraps_for_known_trip_count(ptr noalias %x, ptr noalias %out) { +; CHECK-LABEL: define void @wrap_predicate_for_interleave_group_wraps_for_known_trip_count( +; CHECK-SAME: ptr noalias [[X:%.*]], ptr noalias [[OUT:%.*]]) { +; CHECK-NEXT: [[START:.*]]: +; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] +; CHECK: [[VECTOR_SCEVCHECK]]: +; CHECK-NEXT: [[MUL:%.*]] = call { i4, i1 } @llvm.umul.with.overflow.i4(i4 5, i4 -1) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i4, i1 } [[MUL]], 0 +; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i4, i1 } [[MUL]], 1 +; CHECK-NEXT: br i1 [[MUL_OVERFLOW]], 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: [[TMP0:%.*]] = mul nuw nsw i64 [[INDEX]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 15 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[TMP1]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <20 x i32>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <20 x i32> [[WIDE_VEC]], <20 x i32> poison, <4 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP3]], i32 0 +; CHECK-NEXT: store <4 x i32> [[STRIDED_VEC]], ptr [[TMP5]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 12 +; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 12, %[[MIDDLE_BLOCK]] ], [ 0, %[[START]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_MUL5:%.*]] = mul nuw nsw i64 [[IV]], 5 +; CHECK-NEXT: [[IV_MUL5_MASKED:%.*]] = and i64 [[IV_MUL5]], 15 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[IV_MUL5_MASKED]] +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[OUT_I:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[IV]] +; CHECK-NEXT: store i32 [[V]], ptr [[OUT_I]], align 4 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 16 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +start: + br label %loop + +loop: + %iv = phi i64 [ 0, %start ], [ %iv.next, %loop ] + %iv.next = add nuw nsw i64 %iv, 1 + %iv.mul5 = mul nuw nsw i64 %iv, 5 + %iv.mul5.masked = and i64 %iv.mul5, 15 + %gep = getelementptr inbounds nuw i32, ptr %x, i64 %iv.mul5.masked + %v = load i32, ptr %gep, align 4 + %out.i = getelementptr inbounds nuw i32, ptr %out, i64 %iv + store i32 %v, ptr %out.i, align 4 + %exitcond.not = icmp eq i64 %iv.next, 16 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +; For %gep, we have the following SCEV: ((4 * (zext i4 {0,+,3}<%loop> to i64)) + %x). +; Note the i4 bit wide AddRec {0,+,3}. It may wrap, depending on the trip count. +define void @wrap_predicate_for_interleave_group_unknown_trip_count(ptr noalias %x, ptr noalias %out, i64 %n) { +; CHECK-LABEL: define void @wrap_predicate_for_interleave_group_unknown_trip_count( +; CHECK-SAME: ptr noalias [[X:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: [[START:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] +; CHECK: [[VECTOR_SCEVCHECK]]: +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 +; CHECK-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP0]] to i4 +; CHECK-NEXT: [[MUL:%.*]] = call { i4, i1 } @llvm.umul.with.overflow.i4(i4 3, i4 [[TMP9]]) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i4, i1 } [[MUL]], 0 +; CHECK-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i4, i1 } [[MUL]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], 15 +; CHECK-NEXT: [[TMP10:%.*]] = or i1 [[MUL_OVERFLOW]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP10]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[TMP7]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP8]], 15 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[TMP3]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <12 x i32>, ptr [[TMP4]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <12 x i32> [[WIDE_VEC]], <12 x i32> poison, <4 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP5]], i32 0 +; CHECK-NEXT: store <4 x i32> [[STRIDED_VEC]], ptr [[TMP9]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw 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 [[LOOP6:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[START]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_MUL5:%.*]] = mul nuw nsw i64 [[IV]], 3 +; CHECK-NEXT: [[IV_MUL5_MASKED:%.*]] = and i64 [[IV_MUL5]], 15 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[IV_MUL5_MASKED]] +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[OUT_I:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[IV]] +; CHECK-NEXT: store i32 [[V]], ptr [[OUT_I]], align 4 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +start: + br label %loop + +loop: + %iv = phi i64 [ 0, %start ], [ %iv.next, %loop ] + %iv.next = add nuw nsw i64 %iv, 1 + %iv.mul3 = mul nuw nsw i64 %iv, 3 + %iv.mul3.masked = and i64 %iv.mul3, 15 + %gep = getelementptr inbounds nuw i32, ptr %x, i64 %iv.mul3.masked + %v = load i32, ptr %gep, align 4 + %out.i = getelementptr inbounds nuw i32, ptr %out, i64 %iv + store i32 %v, ptr %out.i, align 4 + %exitcond.not = icmp eq i64 %iv.next, %n + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll b/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll index 8a326c9d0c083..7c2c3883e1dc7 100644 --- a/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll +++ b/llvm/test/Transforms/LoopVectorize/load-deref-pred-align.ll @@ -753,3 +753,133 @@ exit: call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %local_dest, i64 1024, i1 false) ret void } + +define void @adding_offset_overflows(i32 %n, ptr %A) { +; CHECK-LABEL: @adding_offset_overflows( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = alloca [62 x i32], align 4 +; CHECK-NEXT: [[C:%.*]] = alloca [144 x i32], align 4 +; CHECK-NEXT: call void @init(ptr [[B]]) +; CHECK-NEXT: call void @init(ptr [[C]]) +; CHECK-NEXT: [[PRE:%.*]] = icmp slt i32 [[N:%.*]], 1 +; CHECK-NEXT: br i1 [[PRE]], label [[EXIT:%.*]], label [[PH:%.*]] +; CHECK: ph: +; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[N]] to i64 +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 2 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 2 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]] +; CHECK-NEXT: [[TMP1:%.*]] = add i64 1, [[N_VEC]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE3:%.*]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i64 1, [[INDEX]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[A:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i32, ptr [[TMP2]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[TMP23]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[WIDE_LOAD]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0 +; CHECK-NEXT: br i1 [[TMP4]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]] +; CHECK: pred.load.if: +; CHECK-NEXT: [[TMP15:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[B]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 +; CHECK-NEXT: [[TMP18:%.*]] = insertelement <2 x i32> poison, i32 [[TMP17]], i32 0 +; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE]] +; CHECK: pred.load.continue: +; CHECK-NEXT: [[TMP19:%.*]] = phi <2 x i32> [ poison, [[VECTOR_BODY]] ], [ [[TMP18]], [[PRED_LOAD_IF]] ] +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1 +; CHECK-NEXT: br i1 [[TMP20]], label [[PRED_LOAD_IF1:%.*]], label [[PRED_LOAD_CONTINUE2:%.*]] +; CHECK: pred.load.if1: +; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[OFFSET_IDX]], 1 +; CHECK-NEXT: [[TMP22:%.*]] = getelementptr i32, ptr [[B]], i64 [[TMP21]] +; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP22]], align 4 +; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP19]], i32 [[TMP13]], i32 1 +; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE2]] +; CHECK: pred.load.continue2: +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = phi <2 x i32> [ [[TMP19]], [[PRED_LOAD_CONTINUE]] ], [ [[TMP14]], [[PRED_LOAD_IF1]] ] +; CHECK-NEXT: [[TMP5:%.*]] = sext <2 x i32> [[WIDE_LOAD1]] to <2 x i64> +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0 +; CHECK-NEXT: br i1 [[TMP6]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] +; CHECK: pred.store.if: +; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i64> [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i32, ptr [[C]], i64 [[TMP7]] +; CHECK-NEXT: store i32 0, ptr [[TMP8]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] +; CHECK: pred.store.continue: +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1 +; CHECK-NEXT: br i1 [[TMP9]], label [[PRED_STORE_IF2:%.*]], label [[PRED_STORE_CONTINUE3]] +; CHECK: pred.store.if3: +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[TMP5]], i32 1 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[C]], i64 [[TMP10]] +; CHECK-NEXT: store i32 0, ptr [[TMP11]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE3]] +; CHECK: pred.store.continue4: +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[TMP1]], [[MIDDLE_BLOCK]] ], [ 1, [[PH]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]] +; CHECK-NEXT: [[L_A:%.*]] = load i32, ptr [[GEP_A]], align 4 +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[L_A]], 0 +; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr i32, ptr [[B]], i64 [[IV]] +; CHECK-NEXT: [[L_IDX:%.*]] = load i32, ptr [[GEP_B]], align 4 +; CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[L_IDX]] to i64 +; CHECK-NEXT: [[GEP_C:%.*]] = getelementptr i32, ptr [[C]], i64 [[IDX_EXT]] +; CHECK-NEXT: store i32 0, ptr [[GEP_C]], align 4 +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECK-NEXT: br i1 [[EC]], label [[EXIT_LOOPEXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP17:![0-9]+]] +; CHECK: exit.loopexit: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %B = alloca [62 x i32], align 4 + %C = alloca [144 x i32], align 4 + call void @init(ptr %B) + call void @init(ptr %C) + %pre = icmp slt i32 %n, 1 + br i1 %pre, label %exit, label %ph + +ph: + %wide.trip.count = zext i32 %n to i64 + br label %loop.header + +loop.header: + %iv = phi i64 [ 1, %ph ], [ %iv.next, %loop.latch ] + %gep.A = getelementptr i32, ptr %A, i64 %iv + %l.A = load i32, ptr %gep.A, align 4 + %c.1 = icmp eq i32 %l.A, 0 + br i1 %c.1, label %loop.latch, label %if.then + +if.then: + %gep.B = getelementptr i32, ptr %B, i64 %iv + %l.idx = load i32, ptr %gep.B, align 4 + %idx.ext = sext i32 %l.idx to i64 + %gep.C = getelementptr i32, ptr %C, i64 %idx.ext + store i32 0, ptr %gep.C, align 4 + br label %loop.latch + +loop.latch: + %iv.next = add i64 %iv, 1 + %ec = icmp eq i64 %iv.next, %wide.trip.count + br i1 %ec, label %exit, label %loop.header + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopVectorize/minmax_reduction.ll b/llvm/test/Transforms/LoopVectorize/minmax_reduction.ll index 85a90f2e04c5e..e7ab02cd98a5e 100644 --- a/llvm/test/Transforms/LoopVectorize/minmax_reduction.ll +++ b/llvm/test/Transforms/LoopVectorize/minmax_reduction.ll @@ -1001,8 +1001,10 @@ for.body: ; preds = %entry, %for.body br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } +; This can be vectorized with additional runtime checks for NaNs. ; CHECK-LABEL: @fmin_intrinsic_nofast( -; CHECK-NOT: <2 x float> @llvm.minnum.v2f32 +; CHECK: <2 x float> @llvm.minnum.v2f32 +; CHECK: fcmp uno <2 x float> [[OP:.+]], [[OP]] define float @fmin_intrinsic_nofast(ptr nocapture readonly %x) { entry: br label %for.body @@ -1021,8 +1023,10 @@ for.body: ; preds = %entry, %for.body br i1 %exitcond.not, label %for.cond.cleanup, label %for.body } +; This can be vectorized with additional runtime checks for NaNs. ; CHECK-LABEL: @fmax_intrinsic_nofast( -; CHECK-NOT: <2 x float> @llvm.maxnum.v2f32 +; CHECK: <2 x float> @llvm.maxnum.v2f32 +; CHECK: fcmp uno <2 x float> [[OP:.+]], [[OP]] define float @fmax_intrinsic_nofast(ptr nocapture readonly %x) { entry: br label %for.body diff --git a/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll b/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll index a47037c46eedc..7a5cf4576ac9e 100644 --- a/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll +++ b/llvm/test/Transforms/LoopVectorize/runtime-check-small-clamped-bounds.ll @@ -19,6 +19,7 @@ define void @load_clamped_index(ptr %A, ptr %B, i32 %N) { ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]] ; CHECK: vector.scevcheck: ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 +; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP0]] to i2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[TMP0]], 3 ; CHECK-NEXT: br i1 [[TMP1]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]] ; CHECK: vector.memcheck: @@ -91,6 +92,7 @@ define void @store_clamped_index(ptr %A, ptr %B, i32 %N) { ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]] ; CHECK: vector.scevcheck: ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 +; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP0]] to i2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[TMP0]], 3 ; CHECK-NEXT: br i1 [[TMP1]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]] ; CHECK: vector.memcheck: @@ -359,6 +361,7 @@ define void @clamped_index_equal_dependence(ptr %A, ptr %B, i32 %N) { ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]] ; CHECK: vector.scevcheck: ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP0]] to i2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[TMP0]], 3 ; CHECK-NEXT: br i1 [[TMP1]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: diff --git a/llvm/test/Transforms/LoopVersioning/wrapping-pointer-versioning.ll b/llvm/test/Transforms/LoopVersioning/wrapping-pointer-versioning.ll index 6e5eeaf9f1218..3e25695304854 100644 --- a/llvm/test/Transforms/LoopVersioning/wrapping-pointer-versioning.ll +++ b/llvm/test/Transforms/LoopVersioning/wrapping-pointer-versioning.ll @@ -29,7 +29,12 @@ define void @f1(ptr noalias %a, ; LV-LABEL: @f1( ; LV-NEXT: for.body.lver.check: ; LV-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1 +; LV-NEXT: [[TMP5:%.*]] = trunc i64 [[TMP0]] to i32 +; LV-NEXT: [[MUL2:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 2, i32 [[TMP5]]) +; LV-NEXT: [[MUL_RESULT1:%.*]] = extractvalue { i32, i1 } [[MUL2]], 0 +; LV-NEXT: [[MUL_OVERFLOW1:%.*]] = extractvalue { i32, i1 } [[MUL2]], 1 ; LV-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], 4294967295 +; LV-NEXT: [[TMP8:%.*]] = or i1 [[MUL_OVERFLOW1]], [[TMP1]] ; LV-NEXT: [[MUL1:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 4, i64 [[TMP0]]) ; LV-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i64, i1 } [[MUL1]], 0 ; LV-NEXT: [[MUL_OVERFLOW:%.*]] = extractvalue { i64, i1 } [[MUL1]], 1 @@ -37,7 +42,7 @@ define void @f1(ptr noalias %a, ; LV-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 [[MUL_RESULT]] ; LV-NEXT: [[TMP4:%.*]] = icmp ult ptr [[TMP3]], [[A]] ; LV-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[MUL_OVERFLOW]] -; LV-NEXT: [[TMP7:%.*]] = or i1 [[TMP1]], [[TMP6]] +; LV-NEXT: [[TMP7:%.*]] = or i1 [[TMP8]], [[TMP6]] ; LV-NEXT: br i1 [[TMP7]], label [[FOR_BODY_PH_LVER_ORIG:%.*]], label [[FOR_BODY_PH:%.*]] ; LV: for.body.ph.lver.orig: ; LV-NEXT: br label [[FOR_BODY_LVER_ORIG:%.*]] @@ -75,7 +80,7 @@ define void @f1(ptr noalias %a, ; LV-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT2:%.*]], label [[FOR_BODY]] ; LV: for.end.loopexit: ; LV-NEXT: br label [[FOR_END:%.*]] -; LV: for.end.loopexit2: +; LV: for.end.loopexit5: ; LV-NEXT: br label [[FOR_END]] ; LV: for.end: ; LV-NEXT: ret void diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-log.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-log.ll new file mode 100644 index 0000000000000..3a1d1324d8e45 --- /dev/null +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/AArch64/expand-log.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=pre-isel-intrinsic-lowering -S < %s | FileCheck %s +target triple = "aarch64" + +define @scalable_vec_log( %input) { +; CHECK-LABEL: define @scalable_vec_log( +; CHECK-SAME: [[INPUT:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 4 +; CHECK-NEXT: br label %[[BB3:.*]] +; CHECK: [[BB3]]: +; CHECK-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[TMP9:%.*]], %[[BB3]] ] +; CHECK-NEXT: [[TMP5:%.*]] = phi [ [[INPUT]], [[TMP0]] ], [ [[TMP8:%.*]], %[[BB3]] ] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement [[TMP5]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP7:%.*]] = call float @llvm.log.f32(float [[TMP6]]) +; CHECK-NEXT: [[TMP8]] = insertelement [[TMP5]], float [[TMP7]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP9]] = add i64 [[TMP4]], 1 +; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], [[TMP2]] +; CHECK-NEXT: br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB3]] +; CHECK: [[BB11]]: +; CHECK-NEXT: ret [[TMP8]] +; + %output = call @llvm.log.nxv4f32( %input) + ret %output +} + +define <4 x float> @fixed_vec_log(<4 x float> %input) { +; CHECK-LABEL: define <4 x float> @fixed_vec_log( +; CHECK-SAME: <4 x float> [[INPUT:%.*]]) { +; CHECK-NEXT: [[OUTPUT:%.*]] = call <4 x float> @llvm.log.v4f32(<4 x float> [[INPUT]]) +; CHECK-NEXT: ret <4 x float> [[OUTPUT]] +; + %output = call <4 x float> @llvm.log.v4f32(<4 x float> %input) + ret <4 x float> %output +} + +declare <4 x float> @llvm.log.v4f32(<4 x float>) #0 +declare @llvm.log.nxv4f32() #0 + +attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } diff --git a/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll new file mode 100644 index 0000000000000..70ebf220c369c --- /dev/null +++ b/llvm/test/Transforms/RelLookupTableConverter/nvptx.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5 +; RUN: opt < %s -passes=rel-lookup-table-converter -relocation-model=pic -S | FileCheck %s +; REQUIRES: nvptx-registered-target +target triple = "nvptx64-nvidia-cuda" + +; Do not produce relative lookup table for nvptx target. + +@a1 = internal constant i32 0, align 4 +@b1 = internal constant i32 0, align 4 +@c1 = internal constant i32 0, align 4 +@d1 = internal constant i32 0, align 4 + +@switch.table = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr @c1], align 8 + +;. +; CHECK: @a1 = internal constant i32 0, align 4 +; CHECK: @b1 = internal constant i32 0, align 4 +; CHECK: @c1 = internal constant i32 0, align 4 +; CHECK: @d1 = internal constant i32 0, align 4 +; CHECK: @switch.table = private unnamed_addr constant [3 x ptr] [ptr @a1, ptr @b1, ptr @c1], align 8 +;. +define ptr @internal_linkage(i32 %cond) { +; CHECK-LABEL: define ptr @internal_linkage( +; CHECK-SAME: i32 [[COND:%.*]]) { +; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x ptr], ptr @switch.table, i32 0, i32 [[COND]] +; CHECK-NEXT: [[RELTABLE_INTRINSIC:%.*]] = load ptr, ptr [[SWITCH_GEP]], align 8 +; CHECK-NEXT: ret ptr [[RELTABLE_INTRINSIC]] +; + %switch.gep = getelementptr inbounds [3 x ptr], ptr @switch.table, i32 0, i32 %cond + %switch.load = load ptr, ptr %switch.gep, align 8 + ret ptr %switch.load +} diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll index 5e3fd156666f5..410696260a855 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll @@ -16,12 +16,11 @@ define void @test1(<4 x i16> %a, <4 x i16> %b, ptr %p) { ; CHECK-NEXT: [[S0:%.*]] = sext i32 [[E0]] to i64 ; CHECK-NEXT: [[GEP0:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 [[S0]] ; CHECK-NEXT: [[LOAD0:%.*]] = load i64, ptr [[GEP0]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i32> [[SUB0]], <4 x i32> poison, <2 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i32> [[SUB0]], i32 1 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP2]] ; CHECK-NEXT: [[LOAD1:%.*]] = load i64, ptr [[GEP1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i32> [[TMP0]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[SUB0]], i32 2 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP4]] ; CHECK-NEXT: [[LOAD2:%.*]] = load i64, ptr [[GEP2]], align 4 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll index 2b5ee59aeb163..96dd691c4816e 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/external-use-icmp.ll @@ -5,24 +5,21 @@ define i16 @foo(i16 %in1, i16 %in2) { ; CHECK-LABEL: define i16 @foo( ; CHECK-SAME: i16 [[IN1:%.*]], i16 [[IN2:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i16> poison, i16 [[IN1]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i16> [[TMP0]], <2 x i16> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i16> [[TMP1]] to <2 x i64> -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> poison, i16 [[IN2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i16> [[TMP3]] to <2 x i64> -; CHECK-NEXT: [[TMP9:%.*]] = mul nuw nsw <2 x i64> [[TMP5]], [[TMP4]] -; CHECK-NEXT: [[TMP12:%.*]] = and <2 x i64> [[TMP9]], splat (i64 65535) -; CHECK-NEXT: [[TMP7:%.*]] = icmp ne <2 x i64> [[TMP12]], splat (i64 65533) -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x i1> [[TMP7]], i32 1 +; CHECK-NEXT: [[ZEXT1_1:%.*]] = zext i16 [[IN1]] to i64 +; CHECK-NEXT: [[ZEXT2_1:%.*]] = zext i16 [[IN2]] to i64 +; CHECK-NEXT: [[TMP10:%.*]] = mul nuw nsw i64 [[ZEXT2_1]], [[ZEXT1_1]] +; CHECK-NEXT: [[AND1:%.*]] = and i64 [[TMP10]], 65535 +; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i64 [[AND1]], 65533 ; CHECK-NEXT: [[ZEXT3_1:%.*]] = zext i1 [[TMP8]] to i16 -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[TMP9]], i32 1 ; CHECK-NEXT: [[CMP2_1:%.*]] = icmp ne i64 [[TMP10]], 196605 ; CHECK-NEXT: [[ZEXT4_1:%.*]] = zext i1 [[CMP2_1]] to i16 ; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i16 [[ZEXT3_1]], [[ZEXT4_1]] -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP7]], i32 0 +; CHECK-NEXT: [[ZEXT1_2:%.*]] = zext i16 [[IN1]] to i64 +; CHECK-NEXT: [[ZEXT2_2:%.*]] = zext i16 [[IN2]] to i64 +; CHECK-NEXT: [[TMP13:%.*]] = mul nuw nsw i64 [[ZEXT2_2]], [[ZEXT1_2]] +; CHECK-NEXT: [[AND2:%.*]] = and i64 [[TMP13]], 65535 +; CHECK-NEXT: [[TMP11:%.*]] = icmp ne i64 [[AND2]], 65533 ; CHECK-NEXT: [[ZEXT3_2:%.*]] = zext i1 [[TMP11]] to i16 -; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i64> [[TMP9]], i32 0 ; CHECK-NEXT: [[CMP2_2:%.*]] = icmp ne i64 [[TMP13]], 196605 ; CHECK-NEXT: [[ZEXT4_2:%.*]] = zext i1 [[CMP2_2]] to i16 ; CHECK-NEXT: [[ADD2:%.*]] = add nuw nsw i16 [[ADD1]], [[ZEXT4_2]] diff --git a/llvm/test/Transforms/SLPVectorizer/extract-subvector-long-input.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/extract-subvector-long-input.ll similarity index 89% rename from llvm/test/Transforms/SLPVectorizer/extract-subvector-long-input.ll rename to llvm/test/Transforms/SLPVectorizer/AArch64/extract-subvector-long-input.ll index a1f4590a56919..04c69106d97ff 100644 --- a/llvm/test/Transforms/SLPVectorizer/extract-subvector-long-input.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/extract-subvector-long-input.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: %if x86-registered-target %{ opt -passes=slp-vectorizer -S -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s %} -; RUN: %if aarch64-registered-target %{ opt -passes=slp-vectorizer -S -slp-threshold=-99999 -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s %} +; RUN: opt -passes=slp-vectorizer -S -slp-threshold=-99999 -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s define void @test() { ; CHECK-LABEL: define void @test() { diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/extractelements-to-shuffle.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/extractelements-to-shuffle.ll index 667fc41c069e1..10a17f7e3f9a6 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/extractelements-to-shuffle.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/extractelements-to-shuffle.ll @@ -645,20 +645,21 @@ define i1 @tryMapToRange(ptr %values, ptr %result, <2 x i64> %hi, <2 x i64> %lo) ; CHECK-NEXT: [[S1:%.*]] = sext <2 x i1> [[C1]] to <2 x i64> ; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x i64> [[S1]] to <16 x i8> ; CHECK-NEXT: [[A1:%.*]] = and <16 x i8> [[BC1]], +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <16 x i8> [[A1]], i64 0 +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <16 x i8> [[A1]], i64 8 ; CHECK-NEXT: [[C2:%.*]] = icmp slt <2 x i64> [[L]], [[LO:%.*]] ; CHECK-NEXT: [[S2:%.*]] = sext <2 x i1> [[C2]] to <2 x i64> ; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x i64> [[S2]] to <16 x i8> ; CHECK-NEXT: [[A2:%.*]] = and <16 x i8> [[BC2]], +; CHECK-NEXT: [[E3:%.*]] = extractelement <16 x i8> [[A2]], i64 0 +; CHECK-NEXT: [[E4:%.*]] = extractelement <16 x i8> [[A2]], i64 8 ; CHECK-NEXT: [[REASS_SUB:%.*]] = sub <2 x i64> [[L]], [[LO]] ; CHECK-NEXT: [[ADD_I_I_I_I_I_I:%.*]] = add <2 x i64> [[REASS_SUB]], splat (i64 1) ; CHECK-NEXT: store <2 x i64> [[ADD_I_I_I_I_I_I]], ptr [[RESULT:%.*]], align 8 -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i8> [[A1]], <16 x i8> [[A2]], <2 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <16 x i8> [[A1]], <16 x i8> [[A2]], <2 x i32> -; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i8> [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i8> [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP3]], i32 1 ; CHECK-NEXT: [[O3:%.*]] = or i8 [[TMP4]], [[TMP5]] -; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[O3]], 0 +; CHECK-NEXT: [[O2:%.*]] = or i8 [[E4]], [[E3]] +; CHECK-NEXT: [[O4:%.*]] = or i8 [[O3]], [[O2]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[O4]], 0 ; CHECK-NEXT: ret i1 [[C]] ; %l = load <2 x i64>, ptr %values, align 8 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll index 8d7d31ab98441..f397290299a4f 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll @@ -7,54 +7,72 @@ define void @h(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h, i ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CONV9:%.*]] = zext i16 [[A]] to i32 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i16> poison, i16 [[E]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> [[TMP0]], i16 [[I]], i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i16> [[TMP1]], i16 [[M]], i32 2 -; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i16> [[TMP2]], i16 [[B]], i32 3 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i16> [[TMP3]], i32 3 -; CHECK-NEXT: [[TMP5:%.*]] = zext i16 [[TMP4]] to i32 -; CHECK-NEXT: [[SUB:%.*]] = or i32 [[CONV9]], [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i16> poison, i16 [[G]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i16> [[TMP6]], i16 [[K]], i32 1 -; CHECK-NEXT: [[TMP8:%.*]] = insertelement <4 x i16> [[TMP7]], i16 [[O]], i32 2 -; CHECK-NEXT: [[TMP9:%.*]] = insertelement <4 x i16> [[TMP8]], i16 [[C]], i32 3 +; CHECK-NEXT: [[CONV310:%.*]] = zext i16 [[B]] to i32 +; CHECK-NEXT: [[ADD4:%.*]] = or i32 [[CONV310]], [[CONV9]] +; CHECK-NEXT: [[SUB:%.*]] = or i32 [[CONV9]], [[CONV310]] +; CHECK-NEXT: [[CONV15:%.*]] = sext i16 [[C]] to i32 ; CHECK-NEXT: [[SHR:%.*]] = ashr i32 0, 0 +; CHECK-NEXT: [[ARRAYIDX18:%.*]] = getelementptr i8, ptr null, i64 24 ; CHECK-NEXT: [[CONV19:%.*]] = sext i16 [[D]] to i32 ; CHECK-NEXT: [[SUB20:%.*]] = or i32 [[SHR]], [[CONV19]] +; CHECK-NEXT: [[SHR29:%.*]] = ashr i32 0, 0 +; CHECK-NEXT: [[ADD30:%.*]] = or i32 [[SHR29]], [[CONV15]] ; CHECK-NEXT: [[SUB39:%.*]] = or i32 [[SUB]], [[SUB20]] ; CHECK-NEXT: [[CONV40:%.*]] = trunc i32 [[SUB39]] to i16 ; CHECK-NEXT: store i16 [[CONV40]], ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: [[SUB44:%.*]] = or i32 [[ADD4]], [[ADD30]] +; CHECK-NEXT: [[CONV45:%.*]] = trunc i32 [[SUB44]] to i16 +; CHECK-NEXT: store i16 [[CONV45]], ptr [[ARRAYIDX18]], align 2 ; CHECK-NEXT: [[ARRAYIDX2_1:%.*]] = getelementptr i8, ptr null, i64 18 -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i16> [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP11:%.*]] = zext i16 [[TMP10]] to i32 -; CHECK-NEXT: [[ADD4_1:%.*]] = or i32 [[TMP11]], 0 +; CHECK-NEXT: [[CONV3_112:%.*]] = zext i16 [[E]] to i32 +; CHECK-NEXT: [[ADD4_1:%.*]] = or i32 [[CONV3_112]], 0 +; CHECK-NEXT: [[SUB_1:%.*]] = or i32 0, [[CONV3_112]] ; CHECK-NEXT: [[CONV15_1:%.*]] = sext i16 [[F]] to i32 +; CHECK-NEXT: [[SHR_1:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ARRAYIDX18_1:%.*]] = getelementptr i8, ptr null, i64 26 +; CHECK-NEXT: [[CONV19_1:%.*]] = sext i16 [[G]] to i32 +; CHECK-NEXT: [[SUB20_1:%.*]] = or i32 [[SHR_1]], [[CONV19_1]] ; CHECK-NEXT: [[SHR29_1:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ADD30_1:%.*]] = or i32 [[SHR29_1]], [[CONV15_1]] +; CHECK-NEXT: [[SUB39_1:%.*]] = or i32 [[SUB_1]], [[SUB20_1]] +; CHECK-NEXT: [[CONV40_1:%.*]] = trunc i32 [[SUB39_1]] to i16 +; CHECK-NEXT: store i16 [[CONV40_1]], ptr [[ARRAYIDX2_1]], align 2 ; CHECK-NEXT: [[SUB44_1:%.*]] = or i32 [[ADD4_1]], [[ADD30_1]] ; CHECK-NEXT: [[CONV45_1:%.*]] = trunc i32 [[SUB44_1]] to i16 ; CHECK-NEXT: store i16 [[CONV45_1]], ptr [[ARRAYIDX18_1]], align 2 ; CHECK-NEXT: [[CONV_213:%.*]] = zext i16 [[H]] to i32 +; CHECK-NEXT: [[ARRAYIDX2_2:%.*]] = getelementptr i8, ptr null, i64 20 +; CHECK-NEXT: [[CONV3_214:%.*]] = zext i16 [[I]] to i32 ; CHECK-NEXT: [[ADD4_2:%.*]] = or i32 0, [[CONV_213]] +; CHECK-NEXT: [[SUB_2:%.*]] = or i32 0, [[CONV3_214]] ; CHECK-NEXT: [[CONV15_2:%.*]] = sext i16 [[J]] to i32 +; CHECK-NEXT: [[SHR_2:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ARRAYIDX18_2:%.*]] = getelementptr i8, ptr null, i64 28 +; CHECK-NEXT: [[CONV19_2:%.*]] = sext i16 [[K]] to i32 +; CHECK-NEXT: [[SUB20_2:%.*]] = or i32 [[SHR_2]], [[CONV19_2]] ; CHECK-NEXT: [[SHR29_2:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ADD30_2:%.*]] = or i32 [[SHR29_2]], [[CONV15_2]] +; CHECK-NEXT: [[SUB39_2:%.*]] = or i32 [[SUB_2]], [[SUB20_2]] +; CHECK-NEXT: [[CONV40_2:%.*]] = trunc i32 [[SUB39_2]] to i16 +; CHECK-NEXT: store i16 [[CONV40_2]], ptr [[ARRAYIDX2_2]], align 2 ; CHECK-NEXT: [[SUB44_2:%.*]] = or i32 [[ADD4_2]], [[ADD30_2]] ; CHECK-NEXT: [[CONV45_2:%.*]] = trunc i32 [[SUB44_2]] to i16 ; CHECK-NEXT: store i16 [[CONV45_2]], ptr [[ARRAYIDX18_2]], align 2 ; CHECK-NEXT: [[CONV_315:%.*]] = zext i16 [[L]] to i32 +; CHECK-NEXT: [[ARRAYIDX2_3:%.*]] = getelementptr i8, ptr null, i64 22 +; CHECK-NEXT: [[CONV3_316:%.*]] = zext i16 [[M]] to i32 ; CHECK-NEXT: [[ADD4_3:%.*]] = or i32 0, [[CONV_315]] +; CHECK-NEXT: [[SUB_3:%.*]] = or i32 0, [[CONV3_316]] ; CHECK-NEXT: [[CONV15_3:%.*]] = sext i16 [[N]] to i32 +; CHECK-NEXT: [[SHR_3:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ARRAYIDX18_3:%.*]] = getelementptr i8, ptr null, i64 30 +; CHECK-NEXT: [[CONV19_3:%.*]] = sext i16 [[O]] to i32 +; CHECK-NEXT: [[SUB20_3:%.*]] = or i32 [[SHR_3]], [[CONV19_3]] ; CHECK-NEXT: [[SHR29_3:%.*]] = ashr i32 0, 0 ; CHECK-NEXT: [[ADD30_3:%.*]] = or i32 [[SHR29_3]], [[CONV15_3]] -; CHECK-NEXT: [[TMP12:%.*]] = insertelement <4 x i16> , i16 [[A]], i32 3 -; CHECK-NEXT: [[TMP13:%.*]] = or <4 x i16> [[TMP3]], [[TMP12]] -; CHECK-NEXT: [[TMP14:%.*]] = or <4 x i16> zeroinitializer, [[TMP9]] -; CHECK-NEXT: [[TMP15:%.*]] = or <4 x i16> [[TMP13]], [[TMP14]] -; CHECK-NEXT: store <4 x i16> [[TMP15]], ptr [[ARRAYIDX2_1]], align 2 +; CHECK-NEXT: [[SUB39_3:%.*]] = or i32 [[SUB_3]], [[SUB20_3]] +; CHECK-NEXT: [[CONV40_3:%.*]] = trunc i32 [[SUB39_3]] to i16 +; CHECK-NEXT: store i16 [[CONV40_3]], ptr [[ARRAYIDX2_3]], align 2 ; CHECK-NEXT: [[SUB44_3:%.*]] = or i32 [[ADD4_3]], [[ADD30_3]] ; CHECK-NEXT: [[CONV45_3:%.*]] = trunc i32 [[SUB44_3]] to i16 ; CHECK-NEXT: store i16 [[CONV45_3]], ptr [[ARRAYIDX18_3]], align 2 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr.ll index fcbe2d631ba8b..3376fb8910b77 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer -slp-threshold=-12 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer -slp-threshold=-12 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s ; These tests check that we remove from consideration pairs of seed @@ -26,7 +26,7 @@ ; YAML-NEXT: Function: getelementptr_4x32 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'SLP vectorized with cost ' -; YAML-NEXT: - Cost: '4' +; YAML-NEXT: - Cost: '6' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '3' @@ -36,7 +36,7 @@ ; YAML-NEXT: Function: getelementptr_4x32 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'SLP vectorized with cost ' -; YAML-NEXT: - Cost: '6' +; YAML-NEXT: - Cost: '8' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '3' @@ -51,35 +51,39 @@ define i32 @getelementptr_4x32(ptr nocapture readonly %g, i32 %n, i32 %x, i32 %y ; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[Z:%.*]], i32 1 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD16:%.*]] = extractelement <2 x i32> [[TMP17:%.*]], i32 0 ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD16:%.*]], [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD16]], [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM_032:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[ADD16]], [[FOR_BODY]] ] -; CHECK-NEXT: [[T4:%.*]] = shl nsw i32 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = phi <2 x i32> [ zeroinitializer, [[FOR_BODY_PREHEADER]] ], [ [[TMP17]], [[FOR_BODY]] ] +; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x i32> [[TMP6]], i32 1 +; CHECK-NEXT: [[T4:%.*]] = shl nsw i32 [[TMP15]], 1 +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x i32> [[TMP6]], i32 0 ; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x i32> poison, i32 [[T4]], i32 0 ; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP5:%.*]] = add nsw <2 x i32> [[TMP4]], [[TMP0]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i32> [[TMP5]], i32 0 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[G:%.*]], i32 [[TMP6]] +; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i32> [[TMP5]], i32 0 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[G:%.*]], i32 [[TMP12]] ; CHECK-NEXT: [[T6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[T6]], [[SUM_032]] -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i32> [[TMP5]], i32 1 -; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP7]] +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[T6]], [[TMP16]] +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i32> [[TMP5]], i32 1 +; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP11]] ; CHECK-NEXT: [[T8:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4 ; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[ADD1]], [[T8]] -; CHECK-NEXT: [[TMP10:%.*]] = add nsw <2 x i32> [[TMP4]], [[TMP2]] -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i32> [[TMP10]], i32 0 -; CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP9]] +; CHECK-NEXT: [[TMP18:%.*]] = add nsw <2 x i32> [[TMP4]], [[TMP2]] +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i32> [[TMP18]], i32 0 +; CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP13]] ; CHECK-NEXT: [[T10:%.*]] = load i32, ptr [[ARRAYIDX10]], align 4 ; CHECK-NEXT: [[ADD11:%.*]] = add nsw i32 [[ADD6]], [[T10]] -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i32> [[TMP10]], i32 1 -; CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP11]] +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i32> [[TMP18]], i32 1 +; CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP14]] ; CHECK-NEXT: [[T12:%.*]] = load i32, ptr [[ARRAYIDX15]], align 4 -; CHECK-NEXT: [[ADD16]] = add nsw i32 [[ADD11]], [[T12]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x i32> , i32 [[ADD11]], i32 0 +; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x i32> [[TMP6]], i32 [[T12]], i32 0 +; CHECK-NEXT: [[TMP17]] = add nsw <2 x i32> [[TMP19]], [[TMP20]] +; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = extractelement <2 x i32> [[TMP17]], i32 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INDVARS_IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]] ; @@ -129,7 +133,7 @@ for.body: ; YAML: Function: getelementptr_2x32 ; YAML: Args: ; YAML: - String: 'SLP vectorized with cost ' -; YAML: - Cost: '4' +; YAML: - Cost: '8' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '3' @@ -139,36 +143,42 @@ define i32 @getelementptr_2x32(ptr nocapture readonly %g, i32 %n, i32 %x, i32 %y ; CHECK-NEXT: [[CMP31:%.*]] = icmp sgt i32 [[N:%.*]], 0 ; CHECK-NEXT: br i1 [[CMP31]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[Y:%.*]], i32 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> poison, i32 [[Y:%.*]], i32 0 +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> [[TMP4]], i32 [[Z:%.*]], i32 1 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[OP_RDX:%.*]] = extractelement <2 x i32> [[TMP13:%.*]], i32 0 ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OP_RDX:%.*]], [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OP_RDX]], [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[SUM_032:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[OP_RDX]], [[FOR_BODY]] ] -; CHECK-NEXT: [[T4:%.*]] = shl nsw i32 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = phi <2 x i32> [ zeroinitializer, [[FOR_BODY_PREHEADER]] ], [ [[TMP13]], [[FOR_BODY]] ] +; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i32> [[TMP6]], i32 1 +; CHECK-NEXT: [[T4:%.*]] = shl nsw i32 [[TMP12]], 1 +; CHECK-NEXT: [[T5:%.*]] = add nsw i32 [[T4]], 0 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[G:%.*]], i32 [[T5]] +; CHECK-NEXT: [[T6:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i32> [[TMP6]], i32 0 +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[T6]], [[TMP5]] +; CHECK-NEXT: [[T7:%.*]] = add nsw i32 [[T4]], 1 +; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[T7]] +; CHECK-NEXT: [[T8:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[ADD1]], [[T8]] ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> poison, i32 [[T4]], i32 0 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP3:%.*]] = add nsw <2 x i32> [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i32> [[TMP3]], i32 0 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[G:%.*]], i32 [[TMP4]] -; CHECK-NEXT: [[TMP6:%.*]] = load <2 x i32>, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i32> [[TMP3]], i32 1 -; CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP9]] -; CHECK-NEXT: [[T10:%.*]] = load i32, ptr [[ARRAYIDX10]], align 4 -; CHECK-NEXT: [[T11:%.*]] = add nsw i32 [[T4]], [[Z:%.*]] -; CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[T11]] +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i32> [[TMP3]], i32 0 +; CHECK-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP9]] +; CHECK-NEXT: [[T10:%.*]] = load i32, ptr [[ARRAYIDX11]], align 4 +; CHECK-NEXT: [[ADD11:%.*]] = add nsw i32 [[ADD6]], [[T10]] +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i32> [[TMP3]], i32 1 +; CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds i32, ptr [[G]], i32 [[TMP10]] ; CHECK-NEXT: [[T12:%.*]] = load i32, ptr [[ARRAYIDX15]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i32> poison, i32 [[T10]], i32 2 -; CHECK-NEXT: [[TMP8:%.*]] = insertelement <4 x i32> [[TMP7]], i32 [[T12]], i32 3 -; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <4 x i32> [[TMP8]], <4 x i32> [[TMP10]], <4 x i32> -; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP13]]) -; CHECK-NEXT: [[OP_RDX]] = add i32 [[TMP14]], [[SUM_032]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i32 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x i32> , i32 [[ADD11]], i32 0 +; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x i32> [[TMP6]], i32 [[T12]], i32 0 +; CHECK-NEXT: [[TMP13]] = add nsw <2 x i32> [[TMP11]], [[TMP14]] +; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = extractelement <2 x i32> [[TMP13]], i32 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INDVARS_IV_NEXT]], [[N]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]] ; diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll index 1826e19d8e73f..4847149c87a18 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll @@ -14,7 +14,7 @@ ; YAML-NEXT: Function: test_i16_extend ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'SLP vectorized with cost ' -; YAML-NEXT: - Cost: '-20' +; YAML-NEXT: - Cost: '-16 ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '5' ; YAML-NEXT: ... diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/memory-runtime-checks.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/memory-runtime-checks.ll index 9f5744b17cb79..929fb29a4a679 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/memory-runtime-checks.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/memory-runtime-checks.ll @@ -600,15 +600,27 @@ bb15: ; preds = %bb15, %bb14 define void @test_bounds_removed_before_runtime_checks(ptr %A, ptr %B, i1 %c) { ; CHECK-LABEL: @test_bounds_removed_before_runtime_checks( ; CHECK-NEXT: entry: -; CHECK-NEXT: store <2 x i32> , ptr [[A:%.*]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = fmul float 1.000000e+01, 2.000000e+01 +; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i32 +; CHECK-NEXT: [[TMP3:%.*]] = fmul float 3.000000e+01, 2.000000e+01 +; CHECK-NEXT: [[TMP4:%.*]] = fptosi float [[TMP3]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = icmp sgt i32 100, [[TMP2]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], i32 [[TMP2]], i32 10 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 false, i32 0, i32 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 200, [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i32 [[TMP4]], i32 300 +; CHECK-NEXT: [[TMP10:%.*]] = select i1 false, i32 0, i32 [[TMP9]] +; CHECK-NEXT: store i32 [[TMP7]], ptr [[A:%.*]], align 8 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 0, i32 1 +; CHECK-NEXT: store i32 [[TMP10]], ptr [[TMP12]], align 4 ; CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B:%.*]], align 8 ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB23:%.*]], label [[BB14:%.*]] ; CHECK: bb14: -; CHECK-NEXT: [[TMP15:%.*]] = sext i32 10 to i64 +; CHECK-NEXT: [[TMP15:%.*]] = sext i32 [[TMP7]] to i64 ; CHECK-NEXT: [[TMP16:%.*]] = add nsw i64 2, [[TMP15]] ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 [[TMP16]] ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 3 -; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 0, i32 2 +; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT]], ptr [[A]], i64 0, i32 2 ; CHECK-NEXT: store float 0.000000e+00, ptr [[TMP20]], align 8 ; CHECK-NEXT: [[TMP21:%.*]] = load i8, ptr [[TMP19]], align 1 ; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT]], ptr [[A]], i64 0, i32 3 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/multiple_reduction.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/multiple_reduction.ll index 9562e6d41f7cd..fe3db7d462e8e 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/multiple_reduction.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/multiple_reduction.ll @@ -14,168 +14,389 @@ define i64 @straight(ptr nocapture noundef readonly %p, i32 noundef %st) { ; CHECK-LABEL: @straight( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[ST:%.*]] to i64 -; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i16, ptr [[P:%.*]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[P:%.*]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV]] +; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 1 +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX_1]], align 2 +; CHECK-NEXT: [[CONV_1:%.*]] = zext i16 [[TMP1]] to i32 +; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i32 [[CONV]], [[CONV_1]] +; CHECK-NEXT: [[MUL_1:%.*]] = mul nuw nsw i32 [[CONV_1]], [[CONV_1]] +; CHECK-NEXT: [[ADD11_1:%.*]] = add nuw i32 [[MUL_1]], [[MUL]] +; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX_2]], align 2 +; CHECK-NEXT: [[CONV_2:%.*]] = zext i16 [[TMP2]] to i32 +; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i32 [[ADD_1]], [[CONV_2]] +; CHECK-NEXT: [[MUL_2:%.*]] = mul nuw nsw i32 [[CONV_2]], [[CONV_2]] +; CHECK-NEXT: [[ADD11_2:%.*]] = add i32 [[MUL_2]], [[ADD11_1]] +; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 3 +; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX_3]], align 2 +; CHECK-NEXT: [[CONV_3:%.*]] = zext i16 [[TMP3]] to i32 +; CHECK-NEXT: [[ADD_3:%.*]] = add nuw nsw i32 [[ADD_2]], [[CONV_3]] +; CHECK-NEXT: [[MUL_3:%.*]] = mul nuw nsw i32 [[CONV_3]], [[CONV_3]] +; CHECK-NEXT: [[ADD11_3:%.*]] = add i32 [[MUL_3]], [[ADD11_2]] +; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 4 +; CHECK-NEXT: [[TMP4:%.*]] = load i16, ptr [[ARRAYIDX_4]], align 2 +; CHECK-NEXT: [[CONV_4:%.*]] = zext i16 [[TMP4]] to i32 +; CHECK-NEXT: [[ADD_4:%.*]] = add nuw nsw i32 [[ADD_3]], [[CONV_4]] +; CHECK-NEXT: [[MUL_4:%.*]] = mul nuw nsw i32 [[CONV_4]], [[CONV_4]] +; CHECK-NEXT: [[ADD11_4:%.*]] = add i32 [[MUL_4]], [[ADD11_3]] +; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 5 +; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX_5]], align 2 +; CHECK-NEXT: [[CONV_5:%.*]] = zext i16 [[TMP5]] to i32 +; CHECK-NEXT: [[ADD_5:%.*]] = add nuw nsw i32 [[ADD_4]], [[CONV_5]] +; CHECK-NEXT: [[MUL_5:%.*]] = mul nuw nsw i32 [[CONV_5]], [[CONV_5]] +; CHECK-NEXT: [[ADD11_5:%.*]] = add i32 [[MUL_5]], [[ADD11_4]] +; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 6 +; CHECK-NEXT: [[TMP6:%.*]] = load i16, ptr [[ARRAYIDX_6]], align 2 +; CHECK-NEXT: [[CONV_6:%.*]] = zext i16 [[TMP6]] to i32 +; CHECK-NEXT: [[ADD_6:%.*]] = add nuw nsw i32 [[ADD_5]], [[CONV_6]] +; CHECK-NEXT: [[MUL_6:%.*]] = mul nuw nsw i32 [[CONV_6]], [[CONV_6]] +; CHECK-NEXT: [[ADD11_6:%.*]] = add i32 [[MUL_6]], [[ADD11_5]] +; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 7 +; CHECK-NEXT: [[TMP7:%.*]] = load i16, ptr [[ARRAYIDX_7]], align 2 +; CHECK-NEXT: [[CONV_7:%.*]] = zext i16 [[TMP7]] to i32 +; CHECK-NEXT: [[ADD_7:%.*]] = add nuw nsw i32 [[ADD_6]], [[CONV_7]] +; CHECK-NEXT: [[MUL_7:%.*]] = mul nuw nsw i32 [[CONV_7]], [[CONV_7]] +; CHECK-NEXT: [[ADD11_7:%.*]] = add i32 [[MUL_7]], [[ADD11_6]] +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP8:%.*]] = load i16, ptr [[ADD_PTR]], align 2 +; CHECK-NEXT: [[CONV_140:%.*]] = zext i16 [[TMP8]] to i32 +; CHECK-NEXT: [[ADD_141:%.*]] = add nuw nsw i32 [[ADD_7]], [[CONV_140]] +; CHECK-NEXT: [[MUL_142:%.*]] = mul nuw nsw i32 [[CONV_140]], [[CONV_140]] +; CHECK-NEXT: [[ADD11_143:%.*]] = add i32 [[MUL_142]], [[ADD11_7]] +; CHECK-NEXT: [[ARRAYIDX_1_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 1 +; CHECK-NEXT: [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX_1_1]], align 2 +; CHECK-NEXT: [[CONV_1_1:%.*]] = zext i16 [[TMP9]] to i32 +; CHECK-NEXT: [[ADD_1_1:%.*]] = add nuw nsw i32 [[ADD_141]], [[CONV_1_1]] +; CHECK-NEXT: [[MUL_1_1:%.*]] = mul nuw nsw i32 [[CONV_1_1]], [[CONV_1_1]] +; CHECK-NEXT: [[ADD11_1_1:%.*]] = add i32 [[MUL_1_1]], [[ADD11_143]] +; CHECK-NEXT: [[ARRAYIDX_2_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 2 +; CHECK-NEXT: [[TMP10:%.*]] = load i16, ptr [[ARRAYIDX_2_1]], align 2 +; CHECK-NEXT: [[CONV_2_1:%.*]] = zext i16 [[TMP10]] to i32 +; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i32 [[ADD_1_1]], [[CONV_2_1]] +; CHECK-NEXT: [[MUL_2_1:%.*]] = mul nuw nsw i32 [[CONV_2_1]], [[CONV_2_1]] +; CHECK-NEXT: [[ADD11_2_1:%.*]] = add i32 [[MUL_2_1]], [[ADD11_1_1]] +; CHECK-NEXT: [[ARRAYIDX_3_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 3 +; CHECK-NEXT: [[TMP11:%.*]] = load i16, ptr [[ARRAYIDX_3_1]], align 2 +; CHECK-NEXT: [[CONV_3_1:%.*]] = zext i16 [[TMP11]] to i32 +; CHECK-NEXT: [[ADD_3_1:%.*]] = add nuw nsw i32 [[ADD_2_1]], [[CONV_3_1]] +; CHECK-NEXT: [[MUL_3_1:%.*]] = mul nuw nsw i32 [[CONV_3_1]], [[CONV_3_1]] +; CHECK-NEXT: [[ADD11_3_1:%.*]] = add i32 [[MUL_3_1]], [[ADD11_2_1]] +; CHECK-NEXT: [[ARRAYIDX_4_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 4 +; CHECK-NEXT: [[TMP12:%.*]] = load i16, ptr [[ARRAYIDX_4_1]], align 2 +; CHECK-NEXT: [[CONV_4_1:%.*]] = zext i16 [[TMP12]] to i32 +; CHECK-NEXT: [[ADD_4_1:%.*]] = add nuw nsw i32 [[ADD_3_1]], [[CONV_4_1]] +; CHECK-NEXT: [[MUL_4_1:%.*]] = mul nuw nsw i32 [[CONV_4_1]], [[CONV_4_1]] +; CHECK-NEXT: [[ADD11_4_1:%.*]] = add i32 [[MUL_4_1]], [[ADD11_3_1]] +; CHECK-NEXT: [[ARRAYIDX_5_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 5 +; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[ARRAYIDX_5_1]], align 2 +; CHECK-NEXT: [[CONV_5_1:%.*]] = zext i16 [[TMP13]] to i32 +; CHECK-NEXT: [[ADD_5_1:%.*]] = add nuw nsw i32 [[ADD_4_1]], [[CONV_5_1]] +; CHECK-NEXT: [[MUL_5_1:%.*]] = mul nuw nsw i32 [[CONV_5_1]], [[CONV_5_1]] +; CHECK-NEXT: [[ADD11_5_1:%.*]] = add i32 [[MUL_5_1]], [[ADD11_4_1]] +; CHECK-NEXT: [[ARRAYIDX_6_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 6 +; CHECK-NEXT: [[TMP14:%.*]] = load i16, ptr [[ARRAYIDX_6_1]], align 2 +; CHECK-NEXT: [[CONV_6_1:%.*]] = zext i16 [[TMP14]] to i32 +; CHECK-NEXT: [[ADD_6_1:%.*]] = add nuw nsw i32 [[ADD_5_1]], [[CONV_6_1]] +; CHECK-NEXT: [[MUL_6_1:%.*]] = mul nuw nsw i32 [[CONV_6_1]], [[CONV_6_1]] +; CHECK-NEXT: [[ADD11_6_1:%.*]] = add i32 [[MUL_6_1]], [[ADD11_5_1]] +; CHECK-NEXT: [[ARRAYIDX_7_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 7 +; CHECK-NEXT: [[TMP15:%.*]] = load i16, ptr [[ARRAYIDX_7_1]], align 2 +; CHECK-NEXT: [[CONV_7_1:%.*]] = zext i16 [[TMP15]] to i32 +; CHECK-NEXT: [[ADD_7_1:%.*]] = add nuw nsw i32 [[ADD_6_1]], [[CONV_7_1]] +; CHECK-NEXT: [[MUL_7_1:%.*]] = mul nuw nsw i32 [[CONV_7_1]], [[CONV_7_1]] +; CHECK-NEXT: [[ADD11_7_1:%.*]] = add i32 [[MUL_7_1]], [[ADD11_6_1]] ; CHECK-NEXT: [[ADD_PTR_1:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP16:%.*]] = load i16, ptr [[ADD_PTR_1]], align 2 +; CHECK-NEXT: [[CONV_244:%.*]] = zext i16 [[TMP16]] to i32 +; CHECK-NEXT: [[ADD_245:%.*]] = add nuw nsw i32 [[ADD_7_1]], [[CONV_244]] +; CHECK-NEXT: [[MUL_246:%.*]] = mul nuw nsw i32 [[CONV_244]], [[CONV_244]] +; CHECK-NEXT: [[ADD11_247:%.*]] = add i32 [[MUL_246]], [[ADD11_7_1]] +; CHECK-NEXT: [[ARRAYIDX_1_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 1 +; CHECK-NEXT: [[TMP17:%.*]] = load i16, ptr [[ARRAYIDX_1_2]], align 2 +; CHECK-NEXT: [[CONV_1_2:%.*]] = zext i16 [[TMP17]] to i32 +; CHECK-NEXT: [[ADD_1_2:%.*]] = add nuw nsw i32 [[ADD_245]], [[CONV_1_2]] +; CHECK-NEXT: [[MUL_1_2:%.*]] = mul nuw nsw i32 [[CONV_1_2]], [[CONV_1_2]] +; CHECK-NEXT: [[ADD11_1_2:%.*]] = add i32 [[MUL_1_2]], [[ADD11_247]] +; CHECK-NEXT: [[ARRAYIDX_2_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 2 +; CHECK-NEXT: [[TMP18:%.*]] = load i16, ptr [[ARRAYIDX_2_2]], align 2 +; CHECK-NEXT: [[CONV_2_2:%.*]] = zext i16 [[TMP18]] to i32 +; CHECK-NEXT: [[ADD_2_2:%.*]] = add nuw nsw i32 [[ADD_1_2]], [[CONV_2_2]] +; CHECK-NEXT: [[MUL_2_2:%.*]] = mul nuw nsw i32 [[CONV_2_2]], [[CONV_2_2]] +; CHECK-NEXT: [[ADD11_2_2:%.*]] = add i32 [[MUL_2_2]], [[ADD11_1_2]] +; CHECK-NEXT: [[ARRAYIDX_3_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 3 +; CHECK-NEXT: [[TMP19:%.*]] = load i16, ptr [[ARRAYIDX_3_2]], align 2 +; CHECK-NEXT: [[CONV_3_2:%.*]] = zext i16 [[TMP19]] to i32 +; CHECK-NEXT: [[ADD_3_2:%.*]] = add nuw nsw i32 [[ADD_2_2]], [[CONV_3_2]] +; CHECK-NEXT: [[MUL_3_2:%.*]] = mul nuw nsw i32 [[CONV_3_2]], [[CONV_3_2]] +; CHECK-NEXT: [[ADD11_3_2:%.*]] = add i32 [[MUL_3_2]], [[ADD11_2_2]] +; CHECK-NEXT: [[ARRAYIDX_4_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 4 +; CHECK-NEXT: [[TMP20:%.*]] = load i16, ptr [[ARRAYIDX_4_2]], align 2 +; CHECK-NEXT: [[CONV_4_2:%.*]] = zext i16 [[TMP20]] to i32 +; CHECK-NEXT: [[ADD_4_2:%.*]] = add nuw nsw i32 [[ADD_3_2]], [[CONV_4_2]] +; CHECK-NEXT: [[MUL_4_2:%.*]] = mul nuw nsw i32 [[CONV_4_2]], [[CONV_4_2]] +; CHECK-NEXT: [[ADD11_4_2:%.*]] = add i32 [[MUL_4_2]], [[ADD11_3_2]] +; CHECK-NEXT: [[ARRAYIDX_5_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 5 +; CHECK-NEXT: [[TMP21:%.*]] = load i16, ptr [[ARRAYIDX_5_2]], align 2 +; CHECK-NEXT: [[CONV_5_2:%.*]] = zext i16 [[TMP21]] to i32 +; CHECK-NEXT: [[ADD_5_2:%.*]] = add nuw nsw i32 [[ADD_4_2]], [[CONV_5_2]] +; CHECK-NEXT: [[MUL_5_2:%.*]] = mul nuw nsw i32 [[CONV_5_2]], [[CONV_5_2]] +; CHECK-NEXT: [[ADD11_5_2:%.*]] = add i32 [[MUL_5_2]], [[ADD11_4_2]] +; CHECK-NEXT: [[ARRAYIDX_6_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 6 +; CHECK-NEXT: [[TMP22:%.*]] = load i16, ptr [[ARRAYIDX_6_2]], align 2 +; CHECK-NEXT: [[CONV_6_2:%.*]] = zext i16 [[TMP22]] to i32 +; CHECK-NEXT: [[ADD_6_2:%.*]] = add nuw nsw i32 [[ADD_5_2]], [[CONV_6_2]] +; CHECK-NEXT: [[MUL_6_2:%.*]] = mul nuw nsw i32 [[CONV_6_2]], [[CONV_6_2]] +; CHECK-NEXT: [[ADD11_6_2:%.*]] = add i32 [[MUL_6_2]], [[ADD11_5_2]] +; CHECK-NEXT: [[ARRAYIDX_7_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 7 +; CHECK-NEXT: [[TMP23:%.*]] = load i16, ptr [[ARRAYIDX_7_2]], align 2 +; CHECK-NEXT: [[CONV_7_2:%.*]] = zext i16 [[TMP23]] to i32 +; CHECK-NEXT: [[ADD_7_2:%.*]] = add nuw nsw i32 [[ADD_6_2]], [[CONV_7_2]] +; CHECK-NEXT: [[MUL_7_2:%.*]] = mul nuw nsw i32 [[CONV_7_2]], [[CONV_7_2]] +; CHECK-NEXT: [[ADD11_7_2:%.*]] = add i32 [[MUL_7_2]], [[ADD11_6_2]] ; CHECK-NEXT: [[ADD_PTR_2:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_1]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP24:%.*]] = load i16, ptr [[ADD_PTR_2]], align 2 +; CHECK-NEXT: [[CONV_348:%.*]] = zext i16 [[TMP24]] to i32 +; CHECK-NEXT: [[ADD_349:%.*]] = add nuw nsw i32 [[ADD_7_2]], [[CONV_348]] +; CHECK-NEXT: [[MUL_350:%.*]] = mul nuw nsw i32 [[CONV_348]], [[CONV_348]] +; CHECK-NEXT: [[ADD11_351:%.*]] = add i32 [[MUL_350]], [[ADD11_7_2]] +; CHECK-NEXT: [[ARRAYIDX_1_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 1 +; CHECK-NEXT: [[TMP25:%.*]] = load i16, ptr [[ARRAYIDX_1_3]], align 2 +; CHECK-NEXT: [[CONV_1_3:%.*]] = zext i16 [[TMP25]] to i32 +; CHECK-NEXT: [[ADD_1_3:%.*]] = add nuw nsw i32 [[ADD_349]], [[CONV_1_3]] +; CHECK-NEXT: [[MUL_1_3:%.*]] = mul nuw nsw i32 [[CONV_1_3]], [[CONV_1_3]] +; CHECK-NEXT: [[ADD11_1_3:%.*]] = add i32 [[MUL_1_3]], [[ADD11_351]] +; CHECK-NEXT: [[ARRAYIDX_2_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 2 +; CHECK-NEXT: [[TMP26:%.*]] = load i16, ptr [[ARRAYIDX_2_3]], align 2 +; CHECK-NEXT: [[CONV_2_3:%.*]] = zext i16 [[TMP26]] to i32 +; CHECK-NEXT: [[ADD_2_3:%.*]] = add nuw nsw i32 [[ADD_1_3]], [[CONV_2_3]] +; CHECK-NEXT: [[MUL_2_3:%.*]] = mul nuw nsw i32 [[CONV_2_3]], [[CONV_2_3]] +; CHECK-NEXT: [[ADD11_2_3:%.*]] = add i32 [[MUL_2_3]], [[ADD11_1_3]] +; CHECK-NEXT: [[ARRAYIDX_3_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 3 +; CHECK-NEXT: [[TMP27:%.*]] = load i16, ptr [[ARRAYIDX_3_3]], align 2 +; CHECK-NEXT: [[CONV_3_3:%.*]] = zext i16 [[TMP27]] to i32 +; CHECK-NEXT: [[ADD_3_3:%.*]] = add nuw nsw i32 [[ADD_2_3]], [[CONV_3_3]] +; CHECK-NEXT: [[MUL_3_3:%.*]] = mul nuw nsw i32 [[CONV_3_3]], [[CONV_3_3]] +; CHECK-NEXT: [[ADD11_3_3:%.*]] = add i32 [[MUL_3_3]], [[ADD11_2_3]] +; CHECK-NEXT: [[ARRAYIDX_4_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 4 +; CHECK-NEXT: [[TMP28:%.*]] = load i16, ptr [[ARRAYIDX_4_3]], align 2 +; CHECK-NEXT: [[CONV_4_3:%.*]] = zext i16 [[TMP28]] to i32 +; CHECK-NEXT: [[ADD_4_3:%.*]] = add nuw nsw i32 [[ADD_3_3]], [[CONV_4_3]] +; CHECK-NEXT: [[MUL_4_3:%.*]] = mul nuw nsw i32 [[CONV_4_3]], [[CONV_4_3]] +; CHECK-NEXT: [[ADD11_4_3:%.*]] = add i32 [[MUL_4_3]], [[ADD11_3_3]] +; CHECK-NEXT: [[ARRAYIDX_5_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 5 +; CHECK-NEXT: [[TMP29:%.*]] = load i16, ptr [[ARRAYIDX_5_3]], align 2 +; CHECK-NEXT: [[CONV_5_3:%.*]] = zext i16 [[TMP29]] to i32 +; CHECK-NEXT: [[ADD_5_3:%.*]] = add nuw nsw i32 [[ADD_4_3]], [[CONV_5_3]] +; CHECK-NEXT: [[MUL_5_3:%.*]] = mul nuw nsw i32 [[CONV_5_3]], [[CONV_5_3]] +; CHECK-NEXT: [[ADD11_5_3:%.*]] = add i32 [[MUL_5_3]], [[ADD11_4_3]] +; CHECK-NEXT: [[ARRAYIDX_6_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 6 +; CHECK-NEXT: [[TMP30:%.*]] = load i16, ptr [[ARRAYIDX_6_3]], align 2 +; CHECK-NEXT: [[CONV_6_3:%.*]] = zext i16 [[TMP30]] to i32 +; CHECK-NEXT: [[ADD_6_3:%.*]] = add nuw nsw i32 [[ADD_5_3]], [[CONV_6_3]] +; CHECK-NEXT: [[MUL_6_3:%.*]] = mul nuw nsw i32 [[CONV_6_3]], [[CONV_6_3]] +; CHECK-NEXT: [[ADD11_6_3:%.*]] = add i32 [[MUL_6_3]], [[ADD11_5_3]] +; CHECK-NEXT: [[ARRAYIDX_7_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 7 +; CHECK-NEXT: [[TMP31:%.*]] = load i16, ptr [[ARRAYIDX_7_3]], align 2 +; CHECK-NEXT: [[CONV_7_3:%.*]] = zext i16 [[TMP31]] to i32 +; CHECK-NEXT: [[ADD_7_3:%.*]] = add nuw nsw i32 [[ADD_6_3]], [[CONV_7_3]] +; CHECK-NEXT: [[MUL_7_3:%.*]] = mul nuw nsw i32 [[CONV_7_3]], [[CONV_7_3]] +; CHECK-NEXT: [[ADD11_7_3:%.*]] = add i32 [[MUL_7_3]], [[ADD11_6_3]] ; CHECK-NEXT: [[ADD_PTR_3:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_2]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP32:%.*]] = load i16, ptr [[ADD_PTR_3]], align 2 +; CHECK-NEXT: [[CONV_452:%.*]] = zext i16 [[TMP32]] to i32 +; CHECK-NEXT: [[ADD_453:%.*]] = add nuw nsw i32 [[ADD_7_3]], [[CONV_452]] +; CHECK-NEXT: [[MUL_454:%.*]] = mul nuw nsw i32 [[CONV_452]], [[CONV_452]] +; CHECK-NEXT: [[ADD11_455:%.*]] = add i32 [[MUL_454]], [[ADD11_7_3]] +; CHECK-NEXT: [[ARRAYIDX_1_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 1 +; CHECK-NEXT: [[TMP33:%.*]] = load i16, ptr [[ARRAYIDX_1_4]], align 2 +; CHECK-NEXT: [[CONV_1_4:%.*]] = zext i16 [[TMP33]] to i32 +; CHECK-NEXT: [[ADD_1_4:%.*]] = add nuw nsw i32 [[ADD_453]], [[CONV_1_4]] +; CHECK-NEXT: [[MUL_1_4:%.*]] = mul nuw nsw i32 [[CONV_1_4]], [[CONV_1_4]] +; CHECK-NEXT: [[ADD11_1_4:%.*]] = add i32 [[MUL_1_4]], [[ADD11_455]] +; CHECK-NEXT: [[ARRAYIDX_2_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 2 +; CHECK-NEXT: [[TMP34:%.*]] = load i16, ptr [[ARRAYIDX_2_4]], align 2 +; CHECK-NEXT: [[CONV_2_4:%.*]] = zext i16 [[TMP34]] to i32 +; CHECK-NEXT: [[ADD_2_4:%.*]] = add nuw nsw i32 [[ADD_1_4]], [[CONV_2_4]] +; CHECK-NEXT: [[MUL_2_4:%.*]] = mul nuw nsw i32 [[CONV_2_4]], [[CONV_2_4]] +; CHECK-NEXT: [[ADD11_2_4:%.*]] = add i32 [[MUL_2_4]], [[ADD11_1_4]] +; CHECK-NEXT: [[ARRAYIDX_3_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 3 +; CHECK-NEXT: [[TMP35:%.*]] = load i16, ptr [[ARRAYIDX_3_4]], align 2 +; CHECK-NEXT: [[CONV_3_4:%.*]] = zext i16 [[TMP35]] to i32 +; CHECK-NEXT: [[ADD_3_4:%.*]] = add nuw nsw i32 [[ADD_2_4]], [[CONV_3_4]] +; CHECK-NEXT: [[MUL_3_4:%.*]] = mul nuw nsw i32 [[CONV_3_4]], [[CONV_3_4]] +; CHECK-NEXT: [[ADD11_3_4:%.*]] = add i32 [[MUL_3_4]], [[ADD11_2_4]] +; CHECK-NEXT: [[ARRAYIDX_4_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 4 +; CHECK-NEXT: [[TMP36:%.*]] = load i16, ptr [[ARRAYIDX_4_4]], align 2 +; CHECK-NEXT: [[CONV_4_4:%.*]] = zext i16 [[TMP36]] to i32 +; CHECK-NEXT: [[ADD_4_4:%.*]] = add nuw nsw i32 [[ADD_3_4]], [[CONV_4_4]] +; CHECK-NEXT: [[MUL_4_4:%.*]] = mul nuw nsw i32 [[CONV_4_4]], [[CONV_4_4]] +; CHECK-NEXT: [[ADD11_4_4:%.*]] = add i32 [[MUL_4_4]], [[ADD11_3_4]] +; CHECK-NEXT: [[ARRAYIDX_5_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 5 +; CHECK-NEXT: [[TMP37:%.*]] = load i16, ptr [[ARRAYIDX_5_4]], align 2 +; CHECK-NEXT: [[CONV_5_4:%.*]] = zext i16 [[TMP37]] to i32 +; CHECK-NEXT: [[ADD_5_4:%.*]] = add nuw nsw i32 [[ADD_4_4]], [[CONV_5_4]] +; CHECK-NEXT: [[MUL_5_4:%.*]] = mul nuw nsw i32 [[CONV_5_4]], [[CONV_5_4]] +; CHECK-NEXT: [[ADD11_5_4:%.*]] = add i32 [[MUL_5_4]], [[ADD11_4_4]] +; CHECK-NEXT: [[ARRAYIDX_6_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 6 +; CHECK-NEXT: [[TMP38:%.*]] = load i16, ptr [[ARRAYIDX_6_4]], align 2 +; CHECK-NEXT: [[CONV_6_4:%.*]] = zext i16 [[TMP38]] to i32 +; CHECK-NEXT: [[ADD_6_4:%.*]] = add nuw nsw i32 [[ADD_5_4]], [[CONV_6_4]] +; CHECK-NEXT: [[MUL_6_4:%.*]] = mul nuw nsw i32 [[CONV_6_4]], [[CONV_6_4]] +; CHECK-NEXT: [[ADD11_6_4:%.*]] = add i32 [[MUL_6_4]], [[ADD11_5_4]] +; CHECK-NEXT: [[ARRAYIDX_7_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 7 +; CHECK-NEXT: [[TMP39:%.*]] = load i16, ptr [[ARRAYIDX_7_4]], align 2 +; CHECK-NEXT: [[CONV_7_4:%.*]] = zext i16 [[TMP39]] to i32 +; CHECK-NEXT: [[ADD_7_4:%.*]] = add nuw nsw i32 [[ADD_6_4]], [[CONV_7_4]] +; CHECK-NEXT: [[MUL_7_4:%.*]] = mul nuw nsw i32 [[CONV_7_4]], [[CONV_7_4]] +; CHECK-NEXT: [[ADD11_7_4:%.*]] = add i32 [[MUL_7_4]], [[ADD11_6_4]] ; CHECK-NEXT: [[ADD_PTR_4:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_3]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP40:%.*]] = load i16, ptr [[ADD_PTR_4]], align 2 +; CHECK-NEXT: [[CONV_556:%.*]] = zext i16 [[TMP40]] to i32 +; CHECK-NEXT: [[ADD_557:%.*]] = add nuw nsw i32 [[ADD_7_4]], [[CONV_556]] +; CHECK-NEXT: [[MUL_558:%.*]] = mul nuw nsw i32 [[CONV_556]], [[CONV_556]] +; CHECK-NEXT: [[ADD11_559:%.*]] = add i32 [[MUL_558]], [[ADD11_7_4]] +; CHECK-NEXT: [[ARRAYIDX_1_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 1 +; CHECK-NEXT: [[TMP41:%.*]] = load i16, ptr [[ARRAYIDX_1_5]], align 2 +; CHECK-NEXT: [[CONV_1_5:%.*]] = zext i16 [[TMP41]] to i32 +; CHECK-NEXT: [[ADD_1_5:%.*]] = add nuw nsw i32 [[ADD_557]], [[CONV_1_5]] +; CHECK-NEXT: [[MUL_1_5:%.*]] = mul nuw nsw i32 [[CONV_1_5]], [[CONV_1_5]] +; CHECK-NEXT: [[ADD11_1_5:%.*]] = add i32 [[MUL_1_5]], [[ADD11_559]] +; CHECK-NEXT: [[ARRAYIDX_2_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 2 +; CHECK-NEXT: [[TMP42:%.*]] = load i16, ptr [[ARRAYIDX_2_5]], align 2 +; CHECK-NEXT: [[CONV_2_5:%.*]] = zext i16 [[TMP42]] to i32 +; CHECK-NEXT: [[ADD_2_5:%.*]] = add nuw nsw i32 [[ADD_1_5]], [[CONV_2_5]] +; CHECK-NEXT: [[MUL_2_5:%.*]] = mul nuw nsw i32 [[CONV_2_5]], [[CONV_2_5]] +; CHECK-NEXT: [[ADD11_2_5:%.*]] = add i32 [[MUL_2_5]], [[ADD11_1_5]] +; CHECK-NEXT: [[ARRAYIDX_3_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 3 +; CHECK-NEXT: [[TMP43:%.*]] = load i16, ptr [[ARRAYIDX_3_5]], align 2 +; CHECK-NEXT: [[CONV_3_5:%.*]] = zext i16 [[TMP43]] to i32 +; CHECK-NEXT: [[ADD_3_5:%.*]] = add nuw nsw i32 [[ADD_2_5]], [[CONV_3_5]] +; CHECK-NEXT: [[MUL_3_5:%.*]] = mul nuw nsw i32 [[CONV_3_5]], [[CONV_3_5]] +; CHECK-NEXT: [[ADD11_3_5:%.*]] = add i32 [[MUL_3_5]], [[ADD11_2_5]] +; CHECK-NEXT: [[ARRAYIDX_4_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 4 +; CHECK-NEXT: [[TMP44:%.*]] = load i16, ptr [[ARRAYIDX_4_5]], align 2 +; CHECK-NEXT: [[CONV_4_5:%.*]] = zext i16 [[TMP44]] to i32 +; CHECK-NEXT: [[ADD_4_5:%.*]] = add nuw nsw i32 [[ADD_3_5]], [[CONV_4_5]] +; CHECK-NEXT: [[MUL_4_5:%.*]] = mul nuw nsw i32 [[CONV_4_5]], [[CONV_4_5]] +; CHECK-NEXT: [[ADD11_4_5:%.*]] = add i32 [[MUL_4_5]], [[ADD11_3_5]] +; CHECK-NEXT: [[ARRAYIDX_5_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 5 +; CHECK-NEXT: [[TMP45:%.*]] = load i16, ptr [[ARRAYIDX_5_5]], align 2 +; CHECK-NEXT: [[CONV_5_5:%.*]] = zext i16 [[TMP45]] to i32 +; CHECK-NEXT: [[ADD_5_5:%.*]] = add nuw nsw i32 [[ADD_4_5]], [[CONV_5_5]] +; CHECK-NEXT: [[MUL_5_5:%.*]] = mul nuw nsw i32 [[CONV_5_5]], [[CONV_5_5]] +; CHECK-NEXT: [[ADD11_5_5:%.*]] = add i32 [[MUL_5_5]], [[ADD11_4_5]] +; CHECK-NEXT: [[ARRAYIDX_6_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 6 +; CHECK-NEXT: [[TMP46:%.*]] = load i16, ptr [[ARRAYIDX_6_5]], align 2 +; CHECK-NEXT: [[CONV_6_5:%.*]] = zext i16 [[TMP46]] to i32 +; CHECK-NEXT: [[ADD_6_5:%.*]] = add nuw nsw i32 [[ADD_5_5]], [[CONV_6_5]] +; CHECK-NEXT: [[MUL_6_5:%.*]] = mul nuw nsw i32 [[CONV_6_5]], [[CONV_6_5]] +; CHECK-NEXT: [[ADD11_6_5:%.*]] = add i32 [[MUL_6_5]], [[ADD11_5_5]] +; CHECK-NEXT: [[ARRAYIDX_7_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 7 +; CHECK-NEXT: [[TMP47:%.*]] = load i16, ptr [[ARRAYIDX_7_5]], align 2 +; CHECK-NEXT: [[CONV_7_5:%.*]] = zext i16 [[TMP47]] to i32 +; CHECK-NEXT: [[ADD_7_5:%.*]] = add nuw nsw i32 [[ADD_6_5]], [[CONV_7_5]] +; CHECK-NEXT: [[MUL_7_5:%.*]] = mul nuw nsw i32 [[CONV_7_5]], [[CONV_7_5]] +; CHECK-NEXT: [[ADD11_7_5:%.*]] = add i32 [[MUL_7_5]], [[ADD11_6_5]] ; CHECK-NEXT: [[ADD_PTR_5:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_4]], i64 [[IDX_EXT]] +; CHECK-NEXT: [[TMP48:%.*]] = load i16, ptr [[ADD_PTR_5]], align 2 +; CHECK-NEXT: [[CONV_660:%.*]] = zext i16 [[TMP48]] to i32 +; CHECK-NEXT: [[ADD_661:%.*]] = add nuw nsw i32 [[ADD_7_5]], [[CONV_660]] +; CHECK-NEXT: [[MUL_662:%.*]] = mul nuw nsw i32 [[CONV_660]], [[CONV_660]] +; CHECK-NEXT: [[ADD11_663:%.*]] = add i32 [[MUL_662]], [[ADD11_7_5]] +; CHECK-NEXT: [[ARRAYIDX_1_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 1 +; CHECK-NEXT: [[TMP49:%.*]] = load i16, ptr [[ARRAYIDX_1_6]], align 2 +; CHECK-NEXT: [[CONV_1_6:%.*]] = zext i16 [[TMP49]] to i32 +; CHECK-NEXT: [[ADD_1_6:%.*]] = add nuw nsw i32 [[ADD_661]], [[CONV_1_6]] +; CHECK-NEXT: [[MUL_1_6:%.*]] = mul nuw nsw i32 [[CONV_1_6]], [[CONV_1_6]] +; CHECK-NEXT: [[ADD11_1_6:%.*]] = add i32 [[MUL_1_6]], [[ADD11_663]] +; CHECK-NEXT: [[ARRAYIDX_2_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 2 +; CHECK-NEXT: [[TMP50:%.*]] = load i16, ptr [[ARRAYIDX_2_6]], align 2 +; CHECK-NEXT: [[CONV_2_6:%.*]] = zext i16 [[TMP50]] to i32 +; CHECK-NEXT: [[ADD_2_6:%.*]] = add nuw nsw i32 [[ADD_1_6]], [[CONV_2_6]] +; CHECK-NEXT: [[MUL_2_6:%.*]] = mul nuw nsw i32 [[CONV_2_6]], [[CONV_2_6]] +; CHECK-NEXT: [[ADD11_2_6:%.*]] = add i32 [[MUL_2_6]], [[ADD11_1_6]] +; CHECK-NEXT: [[ARRAYIDX_3_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 3 +; CHECK-NEXT: [[TMP51:%.*]] = load i16, ptr [[ARRAYIDX_3_6]], align 2 +; CHECK-NEXT: [[CONV_3_6:%.*]] = zext i16 [[TMP51]] to i32 +; CHECK-NEXT: [[ADD_3_6:%.*]] = add nuw nsw i32 [[ADD_2_6]], [[CONV_3_6]] +; CHECK-NEXT: [[MUL_3_6:%.*]] = mul nuw nsw i32 [[CONV_3_6]], [[CONV_3_6]] +; CHECK-NEXT: [[ADD11_3_6:%.*]] = add i32 [[MUL_3_6]], [[ADD11_2_6]] +; CHECK-NEXT: [[ARRAYIDX_4_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 4 +; CHECK-NEXT: [[TMP52:%.*]] = load i16, ptr [[ARRAYIDX_4_6]], align 2 +; CHECK-NEXT: [[CONV_4_6:%.*]] = zext i16 [[TMP52]] to i32 +; CHECK-NEXT: [[ADD_4_6:%.*]] = add nuw nsw i32 [[ADD_3_6]], [[CONV_4_6]] +; CHECK-NEXT: [[MUL_4_6:%.*]] = mul nuw nsw i32 [[CONV_4_6]], [[CONV_4_6]] +; CHECK-NEXT: [[ADD11_4_6:%.*]] = add i32 [[MUL_4_6]], [[ADD11_3_6]] +; CHECK-NEXT: [[ARRAYIDX_5_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 5 +; CHECK-NEXT: [[TMP53:%.*]] = load i16, ptr [[ARRAYIDX_5_6]], align 2 +; CHECK-NEXT: [[CONV_5_6:%.*]] = zext i16 [[TMP53]] to i32 +; CHECK-NEXT: [[ADD_5_6:%.*]] = add nuw nsw i32 [[ADD_4_6]], [[CONV_5_6]] +; CHECK-NEXT: [[MUL_5_6:%.*]] = mul nuw nsw i32 [[CONV_5_6]], [[CONV_5_6]] +; CHECK-NEXT: [[ADD11_5_6:%.*]] = add i32 [[MUL_5_6]], [[ADD11_4_6]] +; CHECK-NEXT: [[ARRAYIDX_6_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 6 +; CHECK-NEXT: [[TMP54:%.*]] = load i16, ptr [[ARRAYIDX_6_6]], align 2 +; CHECK-NEXT: [[CONV_6_6:%.*]] = zext i16 [[TMP54]] to i32 +; CHECK-NEXT: [[ADD_6_6:%.*]] = add nuw nsw i32 [[ADD_5_6]], [[CONV_6_6]] +; CHECK-NEXT: [[MUL_6_6:%.*]] = mul nuw nsw i32 [[CONV_6_6]], [[CONV_6_6]] +; CHECK-NEXT: [[ADD11_6_6:%.*]] = add i32 [[MUL_6_6]], [[ADD11_5_6]] +; CHECK-NEXT: [[ARRAYIDX_7_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 7 +; CHECK-NEXT: [[TMP55:%.*]] = load i16, ptr [[ARRAYIDX_7_6]], align 2 +; CHECK-NEXT: [[CONV_7_6:%.*]] = zext i16 [[TMP55]] to i32 +; CHECK-NEXT: [[ADD_7_6:%.*]] = add nuw nsw i32 [[ADD_6_6]], [[CONV_7_6]] +; CHECK-NEXT: [[MUL_7_6:%.*]] = mul nuw nsw i32 [[CONV_7_6]], [[CONV_7_6]] +; CHECK-NEXT: [[ADD11_7_6:%.*]] = add i32 [[MUL_7_6]], [[ADD11_6_6]] ; CHECK-NEXT: [[ADD_PTR_6:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_5]], i64 [[IDX_EXT]] -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr [[P]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i16>, ptr [[ADD_PTR]], align 2 -; CHECK-NEXT: [[TMP2:%.*]] = load <8 x i16>, ptr [[ADD_PTR_1]], align 2 -; CHECK-NEXT: [[TMP3:%.*]] = load <8 x i16>, ptr [[ADD_PTR_2]], align 2 -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i16>, ptr [[ADD_PTR_3]], align 2 -; CHECK-NEXT: [[TMP5:%.*]] = load <8 x i16>, ptr [[ADD_PTR_4]], align 2 -; CHECK-NEXT: [[TMP6:%.*]] = load <8 x i16>, ptr [[ADD_PTR_5]], align 2 -; CHECK-NEXT: [[TMP7:%.*]] = load <8 x i16>, ptr [[ADD_PTR_6]], align 2 -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <8 x i16> [[TMP0]], <8 x i16> [[TMP1]], <64 x i32> -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i16> [[TMP2]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <64 x i16> [[TMP10]], <64 x i16> [[TMP11]], <64 x i32> -; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <8 x i16> [[TMP3]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <64 x i16> [[TMP12]], <64 x i16> [[TMP13]], <64 x i32> -; CHECK-NEXT: [[TMP83:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP84:%.*]] = shufflevector <64 x i16> [[TMP14]], <64 x i16> [[TMP83]], <64 x i32> -; CHECK-NEXT: [[TMP85:%.*]] = shufflevector <8 x i16> [[TMP5]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP86:%.*]] = shufflevector <64 x i16> [[TMP84]], <64 x i16> [[TMP85]], <64 x i32> -; CHECK-NEXT: [[TMP87:%.*]] = shufflevector <8 x i16> [[TMP6]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP88:%.*]] = shufflevector <64 x i16> [[TMP86]], <64 x i16> [[TMP87]], <64 x i32> -; CHECK-NEXT: [[TMP89:%.*]] = shufflevector <8 x i16> [[TMP7]], <8 x i16> poison, <64 x i32> -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <64 x i16> [[TMP88]], <64 x i16> [[TMP89]], <64 x i32> -; CHECK-NEXT: [[TMP16:%.*]] = zext <64 x i16> [[TMP15]] to <64 x i32> -; CHECK-NEXT: [[TMP17:%.*]] = extractelement <64 x i32> [[TMP16]], i32 0 -; CHECK-NEXT: [[TMP18:%.*]] = extractelement <64 x i32> [[TMP16]], i32 1 -; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i32 [[TMP17]], [[TMP18]] -; CHECK-NEXT: [[TMP19:%.*]] = mul nuw nsw <64 x i32> [[TMP16]], [[TMP16]] -; CHECK-NEXT: [[TMP20:%.*]] = extractelement <64 x i32> [[TMP16]], i32 2 -; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i32 [[ADD_1]], [[TMP20]] -; CHECK-NEXT: [[TMP21:%.*]] = extractelement <64 x i32> [[TMP16]], i32 3 -; CHECK-NEXT: [[ADD_3:%.*]] = add nuw nsw i32 [[ADD_2]], [[TMP21]] -; CHECK-NEXT: [[TMP22:%.*]] = extractelement <64 x i32> [[TMP16]], i32 4 -; CHECK-NEXT: [[ADD_4:%.*]] = add nuw nsw i32 [[ADD_3]], [[TMP22]] -; CHECK-NEXT: [[TMP23:%.*]] = extractelement <64 x i32> [[TMP16]], i32 5 -; CHECK-NEXT: [[ADD_5:%.*]] = add nuw nsw i32 [[ADD_4]], [[TMP23]] -; CHECK-NEXT: [[TMP24:%.*]] = extractelement <64 x i32> [[TMP16]], i32 6 -; CHECK-NEXT: [[ADD_6:%.*]] = add nuw nsw i32 [[ADD_5]], [[TMP24]] -; CHECK-NEXT: [[TMP25:%.*]] = extractelement <64 x i32> [[TMP16]], i32 7 -; CHECK-NEXT: [[ADD_7:%.*]] = add nuw nsw i32 [[ADD_6]], [[TMP25]] -; CHECK-NEXT: [[TMP26:%.*]] = extractelement <64 x i32> [[TMP16]], i32 8 -; CHECK-NEXT: [[ADD_141:%.*]] = add nuw nsw i32 [[ADD_7]], [[TMP26]] -; CHECK-NEXT: [[TMP27:%.*]] = extractelement <64 x i32> [[TMP16]], i32 9 -; CHECK-NEXT: [[ADD_1_1:%.*]] = add nuw nsw i32 [[ADD_141]], [[TMP27]] -; CHECK-NEXT: [[TMP28:%.*]] = extractelement <64 x i32> [[TMP16]], i32 10 -; CHECK-NEXT: [[ADD_2_1:%.*]] = add nuw nsw i32 [[ADD_1_1]], [[TMP28]] -; CHECK-NEXT: [[TMP29:%.*]] = extractelement <64 x i32> [[TMP16]], i32 11 -; CHECK-NEXT: [[ADD_3_1:%.*]] = add nuw nsw i32 [[ADD_2_1]], [[TMP29]] -; CHECK-NEXT: [[TMP30:%.*]] = extractelement <64 x i32> [[TMP16]], i32 12 -; CHECK-NEXT: [[ADD_4_1:%.*]] = add nuw nsw i32 [[ADD_3_1]], [[TMP30]] -; CHECK-NEXT: [[TMP31:%.*]] = extractelement <64 x i32> [[TMP16]], i32 13 -; CHECK-NEXT: [[ADD_5_1:%.*]] = add nuw nsw i32 [[ADD_4_1]], [[TMP31]] -; CHECK-NEXT: [[TMP32:%.*]] = extractelement <64 x i32> [[TMP16]], i32 14 -; CHECK-NEXT: [[ADD_6_1:%.*]] = add nuw nsw i32 [[ADD_5_1]], [[TMP32]] -; CHECK-NEXT: [[TMP33:%.*]] = extractelement <64 x i32> [[TMP16]], i32 15 -; CHECK-NEXT: [[ADD_7_1:%.*]] = add nuw nsw i32 [[ADD_6_1]], [[TMP33]] -; CHECK-NEXT: [[TMP34:%.*]] = extractelement <64 x i32> [[TMP16]], i32 16 -; CHECK-NEXT: [[ADD_245:%.*]] = add nuw nsw i32 [[ADD_7_1]], [[TMP34]] -; CHECK-NEXT: [[TMP35:%.*]] = extractelement <64 x i32> [[TMP16]], i32 17 -; CHECK-NEXT: [[ADD_1_2:%.*]] = add nuw nsw i32 [[ADD_245]], [[TMP35]] -; CHECK-NEXT: [[TMP36:%.*]] = extractelement <64 x i32> [[TMP16]], i32 18 -; CHECK-NEXT: [[ADD_2_2:%.*]] = add nuw nsw i32 [[ADD_1_2]], [[TMP36]] -; CHECK-NEXT: [[TMP37:%.*]] = extractelement <64 x i32> [[TMP16]], i32 19 -; CHECK-NEXT: [[ADD_3_2:%.*]] = add nuw nsw i32 [[ADD_2_2]], [[TMP37]] -; CHECK-NEXT: [[TMP38:%.*]] = extractelement <64 x i32> [[TMP16]], i32 20 -; CHECK-NEXT: [[ADD_4_2:%.*]] = add nuw nsw i32 [[ADD_3_2]], [[TMP38]] -; CHECK-NEXT: [[TMP39:%.*]] = extractelement <64 x i32> [[TMP16]], i32 21 -; CHECK-NEXT: [[ADD_5_2:%.*]] = add nuw nsw i32 [[ADD_4_2]], [[TMP39]] -; CHECK-NEXT: [[TMP40:%.*]] = extractelement <64 x i32> [[TMP16]], i32 22 -; CHECK-NEXT: [[ADD_6_2:%.*]] = add nuw nsw i32 [[ADD_5_2]], [[TMP40]] -; CHECK-NEXT: [[TMP41:%.*]] = extractelement <64 x i32> [[TMP16]], i32 23 -; CHECK-NEXT: [[ADD_7_2:%.*]] = add nuw nsw i32 [[ADD_6_2]], [[TMP41]] -; CHECK-NEXT: [[TMP42:%.*]] = extractelement <64 x i32> [[TMP16]], i32 24 -; CHECK-NEXT: [[ADD_349:%.*]] = add nuw nsw i32 [[ADD_7_2]], [[TMP42]] -; CHECK-NEXT: [[TMP43:%.*]] = extractelement <64 x i32> [[TMP16]], i32 25 -; CHECK-NEXT: [[ADD_1_3:%.*]] = add nuw nsw i32 [[ADD_349]], [[TMP43]] -; CHECK-NEXT: [[TMP44:%.*]] = extractelement <64 x i32> [[TMP16]], i32 26 -; CHECK-NEXT: [[ADD_2_3:%.*]] = add nuw nsw i32 [[ADD_1_3]], [[TMP44]] -; CHECK-NEXT: [[TMP45:%.*]] = extractelement <64 x i32> [[TMP16]], i32 27 -; CHECK-NEXT: [[ADD_3_3:%.*]] = add nuw nsw i32 [[ADD_2_3]], [[TMP45]] -; CHECK-NEXT: [[TMP46:%.*]] = extractelement <64 x i32> [[TMP16]], i32 28 -; CHECK-NEXT: [[ADD_4_3:%.*]] = add nuw nsw i32 [[ADD_3_3]], [[TMP46]] -; CHECK-NEXT: [[TMP47:%.*]] = extractelement <64 x i32> [[TMP16]], i32 29 -; CHECK-NEXT: [[ADD_5_3:%.*]] = add nuw nsw i32 [[ADD_4_3]], [[TMP47]] -; CHECK-NEXT: [[TMP48:%.*]] = extractelement <64 x i32> [[TMP16]], i32 30 -; CHECK-NEXT: [[ADD_6_3:%.*]] = add nuw nsw i32 [[ADD_5_3]], [[TMP48]] -; CHECK-NEXT: [[TMP49:%.*]] = extractelement <64 x i32> [[TMP16]], i32 31 -; CHECK-NEXT: [[ADD_7_3:%.*]] = add nuw nsw i32 [[ADD_6_3]], [[TMP49]] -; CHECK-NEXT: [[TMP50:%.*]] = extractelement <64 x i32> [[TMP16]], i32 32 -; CHECK-NEXT: [[ADD_453:%.*]] = add nuw nsw i32 [[ADD_7_3]], [[TMP50]] -; CHECK-NEXT: [[TMP51:%.*]] = extractelement <64 x i32> [[TMP16]], i32 33 -; CHECK-NEXT: [[ADD_1_4:%.*]] = add nuw nsw i32 [[ADD_453]], [[TMP51]] -; CHECK-NEXT: [[TMP52:%.*]] = extractelement <64 x i32> [[TMP16]], i32 34 -; CHECK-NEXT: [[ADD_2_4:%.*]] = add nuw nsw i32 [[ADD_1_4]], [[TMP52]] -; CHECK-NEXT: [[TMP53:%.*]] = extractelement <64 x i32> [[TMP16]], i32 35 -; CHECK-NEXT: [[ADD_3_4:%.*]] = add nuw nsw i32 [[ADD_2_4]], [[TMP53]] -; CHECK-NEXT: [[TMP54:%.*]] = extractelement <64 x i32> [[TMP16]], i32 36 -; CHECK-NEXT: [[ADD_4_4:%.*]] = add nuw nsw i32 [[ADD_3_4]], [[TMP54]] -; CHECK-NEXT: [[TMP55:%.*]] = extractelement <64 x i32> [[TMP16]], i32 37 -; CHECK-NEXT: [[ADD_5_4:%.*]] = add nuw nsw i32 [[ADD_4_4]], [[TMP55]] -; CHECK-NEXT: [[TMP56:%.*]] = extractelement <64 x i32> [[TMP16]], i32 38 -; CHECK-NEXT: [[ADD_6_4:%.*]] = add nuw nsw i32 [[ADD_5_4]], [[TMP56]] -; CHECK-NEXT: [[TMP57:%.*]] = extractelement <64 x i32> [[TMP16]], i32 39 -; CHECK-NEXT: [[ADD_7_4:%.*]] = add nuw nsw i32 [[ADD_6_4]], [[TMP57]] -; CHECK-NEXT: [[TMP58:%.*]] = extractelement <64 x i32> [[TMP16]], i32 40 -; CHECK-NEXT: [[ADD_557:%.*]] = add nuw nsw i32 [[ADD_7_4]], [[TMP58]] -; CHECK-NEXT: [[TMP59:%.*]] = extractelement <64 x i32> [[TMP16]], i32 41 -; CHECK-NEXT: [[ADD_1_5:%.*]] = add nuw nsw i32 [[ADD_557]], [[TMP59]] -; CHECK-NEXT: [[TMP60:%.*]] = extractelement <64 x i32> [[TMP16]], i32 42 -; CHECK-NEXT: [[ADD_2_5:%.*]] = add nuw nsw i32 [[ADD_1_5]], [[TMP60]] -; CHECK-NEXT: [[TMP61:%.*]] = extractelement <64 x i32> [[TMP16]], i32 43 -; CHECK-NEXT: [[ADD_3_5:%.*]] = add nuw nsw i32 [[ADD_2_5]], [[TMP61]] -; CHECK-NEXT: [[TMP62:%.*]] = extractelement <64 x i32> [[TMP16]], i32 44 -; CHECK-NEXT: [[ADD_4_5:%.*]] = add nuw nsw i32 [[ADD_3_5]], [[TMP62]] -; CHECK-NEXT: [[TMP63:%.*]] = extractelement <64 x i32> [[TMP16]], i32 45 -; CHECK-NEXT: [[ADD_5_5:%.*]] = add nuw nsw i32 [[ADD_4_5]], [[TMP63]] -; CHECK-NEXT: [[TMP64:%.*]] = extractelement <64 x i32> [[TMP16]], i32 46 -; CHECK-NEXT: [[ADD_6_5:%.*]] = add nuw nsw i32 [[ADD_5_5]], [[TMP64]] -; CHECK-NEXT: [[TMP65:%.*]] = extractelement <64 x i32> [[TMP16]], i32 47 -; CHECK-NEXT: [[ADD_7_5:%.*]] = add nuw nsw i32 [[ADD_6_5]], [[TMP65]] -; CHECK-NEXT: [[TMP66:%.*]] = extractelement <64 x i32> [[TMP16]], i32 48 -; CHECK-NEXT: [[ADD_661:%.*]] = add nuw nsw i32 [[ADD_7_5]], [[TMP66]] -; CHECK-NEXT: [[TMP67:%.*]] = extractelement <64 x i32> [[TMP16]], i32 49 -; CHECK-NEXT: [[ADD_1_6:%.*]] = add nuw nsw i32 [[ADD_661]], [[TMP67]] -; CHECK-NEXT: [[TMP68:%.*]] = extractelement <64 x i32> [[TMP16]], i32 50 -; CHECK-NEXT: [[ADD_2_6:%.*]] = add nuw nsw i32 [[ADD_1_6]], [[TMP68]] -; CHECK-NEXT: [[TMP69:%.*]] = extractelement <64 x i32> [[TMP16]], i32 51 -; CHECK-NEXT: [[ADD_3_6:%.*]] = add nuw nsw i32 [[ADD_2_6]], [[TMP69]] -; CHECK-NEXT: [[TMP70:%.*]] = extractelement <64 x i32> [[TMP16]], i32 52 -; CHECK-NEXT: [[ADD_4_6:%.*]] = add nuw nsw i32 [[ADD_3_6]], [[TMP70]] -; CHECK-NEXT: [[TMP71:%.*]] = extractelement <64 x i32> [[TMP16]], i32 53 -; CHECK-NEXT: [[ADD_5_6:%.*]] = add nuw nsw i32 [[ADD_4_6]], [[TMP71]] -; CHECK-NEXT: [[TMP72:%.*]] = extractelement <64 x i32> [[TMP16]], i32 54 -; CHECK-NEXT: [[ADD_6_6:%.*]] = add nuw nsw i32 [[ADD_5_6]], [[TMP72]] -; CHECK-NEXT: [[TMP73:%.*]] = extractelement <64 x i32> [[TMP16]], i32 55 -; CHECK-NEXT: [[ADD_7_6:%.*]] = add nuw nsw i32 [[ADD_6_6]], [[TMP73]] -; CHECK-NEXT: [[TMP74:%.*]] = extractelement <64 x i32> [[TMP16]], i32 56 -; CHECK-NEXT: [[ADD_765:%.*]] = add nuw nsw i32 [[ADD_7_6]], [[TMP74]] -; CHECK-NEXT: [[TMP75:%.*]] = extractelement <64 x i32> [[TMP16]], i32 57 -; CHECK-NEXT: [[ADD_1_7:%.*]] = add nuw nsw i32 [[ADD_765]], [[TMP75]] -; CHECK-NEXT: [[TMP76:%.*]] = extractelement <64 x i32> [[TMP16]], i32 58 -; CHECK-NEXT: [[ADD_2_7:%.*]] = add nuw nsw i32 [[ADD_1_7]], [[TMP76]] -; CHECK-NEXT: [[TMP77:%.*]] = extractelement <64 x i32> [[TMP16]], i32 59 -; CHECK-NEXT: [[ADD_3_7:%.*]] = add nuw nsw i32 [[ADD_2_7]], [[TMP77]] -; CHECK-NEXT: [[TMP78:%.*]] = extractelement <64 x i32> [[TMP16]], i32 60 -; CHECK-NEXT: [[ADD_4_7:%.*]] = add nuw nsw i32 [[ADD_3_7]], [[TMP78]] -; CHECK-NEXT: [[TMP79:%.*]] = extractelement <64 x i32> [[TMP16]], i32 61 -; CHECK-NEXT: [[ADD_5_7:%.*]] = add nuw nsw i32 [[ADD_4_7]], [[TMP79]] -; CHECK-NEXT: [[TMP80:%.*]] = extractelement <64 x i32> [[TMP16]], i32 62 -; CHECK-NEXT: [[ADD_6_7:%.*]] = add nuw nsw i32 [[ADD_5_7]], [[TMP80]] -; CHECK-NEXT: [[TMP81:%.*]] = extractelement <64 x i32> [[TMP16]], i32 63 -; CHECK-NEXT: [[ADD_7_7:%.*]] = add nuw nsw i32 [[ADD_6_7]], [[TMP81]] -; CHECK-NEXT: [[TMP82:%.*]] = call i32 @llvm.vector.reduce.add.v64i32(<64 x i32> [[TMP19]]) +; CHECK-NEXT: [[TMP56:%.*]] = load i16, ptr [[ADD_PTR_6]], align 2 +; CHECK-NEXT: [[CONV_764:%.*]] = zext i16 [[TMP56]] to i32 +; CHECK-NEXT: [[ADD_765:%.*]] = add nuw nsw i32 [[ADD_7_6]], [[CONV_764]] +; CHECK-NEXT: [[MUL_766:%.*]] = mul nuw nsw i32 [[CONV_764]], [[CONV_764]] +; CHECK-NEXT: [[ADD11_767:%.*]] = add i32 [[MUL_766]], [[ADD11_7_6]] +; CHECK-NEXT: [[ARRAYIDX_1_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 1 +; CHECK-NEXT: [[TMP57:%.*]] = load i16, ptr [[ARRAYIDX_1_7]], align 2 +; CHECK-NEXT: [[CONV_1_7:%.*]] = zext i16 [[TMP57]] to i32 +; CHECK-NEXT: [[ADD_1_7:%.*]] = add nuw nsw i32 [[ADD_765]], [[CONV_1_7]] +; CHECK-NEXT: [[MUL_1_7:%.*]] = mul nuw nsw i32 [[CONV_1_7]], [[CONV_1_7]] +; CHECK-NEXT: [[ADD11_1_7:%.*]] = add i32 [[MUL_1_7]], [[ADD11_767]] +; CHECK-NEXT: [[ARRAYIDX_2_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 2 +; CHECK-NEXT: [[TMP58:%.*]] = load i16, ptr [[ARRAYIDX_2_7]], align 2 +; CHECK-NEXT: [[CONV_2_7:%.*]] = zext i16 [[TMP58]] to i32 +; CHECK-NEXT: [[ADD_2_7:%.*]] = add nuw nsw i32 [[ADD_1_7]], [[CONV_2_7]] +; CHECK-NEXT: [[MUL_2_7:%.*]] = mul nuw nsw i32 [[CONV_2_7]], [[CONV_2_7]] +; CHECK-NEXT: [[ADD11_2_7:%.*]] = add i32 [[MUL_2_7]], [[ADD11_1_7]] +; CHECK-NEXT: [[ARRAYIDX_3_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 3 +; CHECK-NEXT: [[TMP59:%.*]] = load i16, ptr [[ARRAYIDX_3_7]], align 2 +; CHECK-NEXT: [[CONV_3_7:%.*]] = zext i16 [[TMP59]] to i32 +; CHECK-NEXT: [[ADD_3_7:%.*]] = add nuw nsw i32 [[ADD_2_7]], [[CONV_3_7]] +; CHECK-NEXT: [[MUL_3_7:%.*]] = mul nuw nsw i32 [[CONV_3_7]], [[CONV_3_7]] +; CHECK-NEXT: [[ADD11_3_7:%.*]] = add i32 [[MUL_3_7]], [[ADD11_2_7]] +; CHECK-NEXT: [[ARRAYIDX_4_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 4 +; CHECK-NEXT: [[TMP60:%.*]] = load i16, ptr [[ARRAYIDX_4_7]], align 2 +; CHECK-NEXT: [[CONV_4_7:%.*]] = zext i16 [[TMP60]] to i32 +; CHECK-NEXT: [[ADD_4_7:%.*]] = add nuw nsw i32 [[ADD_3_7]], [[CONV_4_7]] +; CHECK-NEXT: [[MUL_4_7:%.*]] = mul nuw nsw i32 [[CONV_4_7]], [[CONV_4_7]] +; CHECK-NEXT: [[ADD11_4_7:%.*]] = add i32 [[MUL_4_7]], [[ADD11_3_7]] +; CHECK-NEXT: [[ARRAYIDX_5_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 5 +; CHECK-NEXT: [[TMP61:%.*]] = load i16, ptr [[ARRAYIDX_5_7]], align 2 +; CHECK-NEXT: [[CONV_5_7:%.*]] = zext i16 [[TMP61]] to i32 +; CHECK-NEXT: [[ADD_5_7:%.*]] = add nuw nsw i32 [[ADD_4_7]], [[CONV_5_7]] +; CHECK-NEXT: [[MUL_5_7:%.*]] = mul nuw nsw i32 [[CONV_5_7]], [[CONV_5_7]] +; CHECK-NEXT: [[ADD11_5_7:%.*]] = add i32 [[MUL_5_7]], [[ADD11_4_7]] +; CHECK-NEXT: [[ARRAYIDX_6_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 6 +; CHECK-NEXT: [[TMP62:%.*]] = load i16, ptr [[ARRAYIDX_6_7]], align 2 +; CHECK-NEXT: [[CONV_6_7:%.*]] = zext i16 [[TMP62]] to i32 +; CHECK-NEXT: [[ADD_6_7:%.*]] = add nuw nsw i32 [[ADD_5_7]], [[CONV_6_7]] +; CHECK-NEXT: [[MUL_6_7:%.*]] = mul nuw nsw i32 [[CONV_6_7]], [[CONV_6_7]] +; CHECK-NEXT: [[ADD11_6_7:%.*]] = add i32 [[MUL_6_7]], [[ADD11_5_7]] +; CHECK-NEXT: [[ARRAYIDX_7_7:%.*]] = getelementptr inbounds i16, ptr [[ADD_PTR_6]], i64 7 +; CHECK-NEXT: [[TMP63:%.*]] = load i16, ptr [[ARRAYIDX_7_7]], align 2 +; CHECK-NEXT: [[CONV_7_7:%.*]] = zext i16 [[TMP63]] to i32 +; CHECK-NEXT: [[ADD_7_7:%.*]] = add nuw nsw i32 [[ADD_6_7]], [[CONV_7_7]] +; CHECK-NEXT: [[MUL_7_7:%.*]] = mul nuw nsw i32 [[CONV_7_7]], [[CONV_7_7]] +; CHECK-NEXT: [[ADD11_7_7:%.*]] = add i32 [[MUL_7_7]], [[ADD11_6_7]] ; CHECK-NEXT: [[CONV15:%.*]] = zext i32 [[ADD_7_7]] to i64 -; CHECK-NEXT: [[CONV16:%.*]] = zext i32 [[TMP82]] to i64 +; CHECK-NEXT: [[CONV16:%.*]] = zext i32 [[ADD11_7_7]] to i64 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[CONV16]], 32 ; CHECK-NEXT: [[ADD17:%.*]] = or i64 [[SHL]], [[CONV15]] ; CHECK-NEXT: ret i64 [[ADD17]] @@ -580,13 +801,101 @@ define i64 @looped(ptr nocapture noundef readonly %p, i32 noundef %st) { ; CHECK-NEXT: [[SQ_037:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[OP_RDX:%.*]], [[FOR_COND1_PREHEADER]] ] ; CHECK-NEXT: [[SM_036:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[OP_RDX1:%.*]], [[FOR_COND1_PREHEADER]] ] ; CHECK-NEXT: [[P_ADDR_035:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY]] ], [ [[ADD_PTR:%.*]], [[FOR_COND1_PREHEADER]] ] -; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i16>, ptr [[P_ADDR_035]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = zext <16 x i16> [[TMP0]] to <16 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = mul nuw nsw <16 x i32> [[TMP1]], [[TMP1]] -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP1]]) -; CHECK-NEXT: [[OP_RDX1]] = add i32 [[TMP3]], [[SM_036]] -; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP2]]) -; CHECK-NEXT: [[OP_RDX]] = add i32 [[TMP4]], [[SQ_037]] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[P_ADDR_035]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SM_036]], [[CONV]] +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV]], [[CONV]] +; CHECK-NEXT: [[ADD11:%.*]] = add i32 [[MUL]], [[SQ_037]] +; CHECK-NEXT: [[ARRAYIDX_1:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 1 +; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX_1]], align 2 +; CHECK-NEXT: [[CONV_1:%.*]] = zext i16 [[TMP1]] to i32 +; CHECK-NEXT: [[ADD_1:%.*]] = add i32 [[ADD]], [[CONV_1]] +; CHECK-NEXT: [[MUL_1:%.*]] = mul nuw nsw i32 [[CONV_1]], [[CONV_1]] +; CHECK-NEXT: [[ADD11_1:%.*]] = add i32 [[MUL_1]], [[ADD11]] +; CHECK-NEXT: [[ARRAYIDX_2:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX_2]], align 2 +; CHECK-NEXT: [[CONV_2:%.*]] = zext i16 [[TMP2]] to i32 +; CHECK-NEXT: [[ADD_2:%.*]] = add i32 [[ADD_1]], [[CONV_2]] +; CHECK-NEXT: [[MUL_2:%.*]] = mul nuw nsw i32 [[CONV_2]], [[CONV_2]] +; CHECK-NEXT: [[ADD11_2:%.*]] = add i32 [[MUL_2]], [[ADD11_1]] +; CHECK-NEXT: [[ARRAYIDX_3:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 3 +; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX_3]], align 2 +; CHECK-NEXT: [[CONV_3:%.*]] = zext i16 [[TMP3]] to i32 +; CHECK-NEXT: [[ADD_3:%.*]] = add i32 [[ADD_2]], [[CONV_3]] +; CHECK-NEXT: [[MUL_3:%.*]] = mul nuw nsw i32 [[CONV_3]], [[CONV_3]] +; CHECK-NEXT: [[ADD11_3:%.*]] = add i32 [[MUL_3]], [[ADD11_2]] +; CHECK-NEXT: [[ARRAYIDX_4:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 4 +; CHECK-NEXT: [[TMP4:%.*]] = load i16, ptr [[ARRAYIDX_4]], align 2 +; CHECK-NEXT: [[CONV_4:%.*]] = zext i16 [[TMP4]] to i32 +; CHECK-NEXT: [[ADD_4:%.*]] = add i32 [[ADD_3]], [[CONV_4]] +; CHECK-NEXT: [[MUL_4:%.*]] = mul nuw nsw i32 [[CONV_4]], [[CONV_4]] +; CHECK-NEXT: [[ADD11_4:%.*]] = add i32 [[MUL_4]], [[ADD11_3]] +; CHECK-NEXT: [[ARRAYIDX_5:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 5 +; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX_5]], align 2 +; CHECK-NEXT: [[CONV_5:%.*]] = zext i16 [[TMP5]] to i32 +; CHECK-NEXT: [[ADD_5:%.*]] = add i32 [[ADD_4]], [[CONV_5]] +; CHECK-NEXT: [[MUL_5:%.*]] = mul nuw nsw i32 [[CONV_5]], [[CONV_5]] +; CHECK-NEXT: [[ADD11_5:%.*]] = add i32 [[MUL_5]], [[ADD11_4]] +; CHECK-NEXT: [[ARRAYIDX_6:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 6 +; CHECK-NEXT: [[TMP6:%.*]] = load i16, ptr [[ARRAYIDX_6]], align 2 +; CHECK-NEXT: [[CONV_6:%.*]] = zext i16 [[TMP6]] to i32 +; CHECK-NEXT: [[ADD_6:%.*]] = add i32 [[ADD_5]], [[CONV_6]] +; CHECK-NEXT: [[MUL_6:%.*]] = mul nuw nsw i32 [[CONV_6]], [[CONV_6]] +; CHECK-NEXT: [[ADD11_6:%.*]] = add i32 [[MUL_6]], [[ADD11_5]] +; CHECK-NEXT: [[ARRAYIDX_7:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 7 +; CHECK-NEXT: [[TMP7:%.*]] = load i16, ptr [[ARRAYIDX_7]], align 2 +; CHECK-NEXT: [[CONV_7:%.*]] = zext i16 [[TMP7]] to i32 +; CHECK-NEXT: [[ADD_7:%.*]] = add i32 [[ADD_6]], [[CONV_7]] +; CHECK-NEXT: [[MUL_7:%.*]] = mul nuw nsw i32 [[CONV_7]], [[CONV_7]] +; CHECK-NEXT: [[ADD11_7:%.*]] = add i32 [[MUL_7]], [[ADD11_6]] +; CHECK-NEXT: [[ARRAYIDX_8:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 8 +; CHECK-NEXT: [[TMP8:%.*]] = load i16, ptr [[ARRAYIDX_8]], align 2 +; CHECK-NEXT: [[CONV_8:%.*]] = zext i16 [[TMP8]] to i32 +; CHECK-NEXT: [[ADD_8:%.*]] = add i32 [[ADD_7]], [[CONV_8]] +; CHECK-NEXT: [[MUL_8:%.*]] = mul nuw nsw i32 [[CONV_8]], [[CONV_8]] +; CHECK-NEXT: [[ADD11_8:%.*]] = add i32 [[MUL_8]], [[ADD11_7]] +; CHECK-NEXT: [[ARRAYIDX_9:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 9 +; CHECK-NEXT: [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX_9]], align 2 +; CHECK-NEXT: [[CONV_9:%.*]] = zext i16 [[TMP9]] to i32 +; CHECK-NEXT: [[ADD_9:%.*]] = add i32 [[ADD_8]], [[CONV_9]] +; CHECK-NEXT: [[MUL_9:%.*]] = mul nuw nsw i32 [[CONV_9]], [[CONV_9]] +; CHECK-NEXT: [[ADD11_9:%.*]] = add i32 [[MUL_9]], [[ADD11_8]] +; CHECK-NEXT: [[ARRAYIDX_10:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 10 +; CHECK-NEXT: [[TMP10:%.*]] = load i16, ptr [[ARRAYIDX_10]], align 2 +; CHECK-NEXT: [[CONV_10:%.*]] = zext i16 [[TMP10]] to i32 +; CHECK-NEXT: [[ADD_10:%.*]] = add i32 [[ADD_9]], [[CONV_10]] +; CHECK-NEXT: [[MUL_10:%.*]] = mul nuw nsw i32 [[CONV_10]], [[CONV_10]] +; CHECK-NEXT: [[ADD11_10:%.*]] = add i32 [[MUL_10]], [[ADD11_9]] +; CHECK-NEXT: [[ARRAYIDX_11:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 11 +; CHECK-NEXT: [[TMP11:%.*]] = load i16, ptr [[ARRAYIDX_11]], align 2 +; CHECK-NEXT: [[CONV_11:%.*]] = zext i16 [[TMP11]] to i32 +; CHECK-NEXT: [[ADD_11:%.*]] = add i32 [[ADD_10]], [[CONV_11]] +; CHECK-NEXT: [[MUL_11:%.*]] = mul nuw nsw i32 [[CONV_11]], [[CONV_11]] +; CHECK-NEXT: [[ADD11_11:%.*]] = add i32 [[MUL_11]], [[ADD11_10]] +; CHECK-NEXT: [[ARRAYIDX_12:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 12 +; CHECK-NEXT: [[TMP12:%.*]] = load i16, ptr [[ARRAYIDX_12]], align 2 +; CHECK-NEXT: [[CONV_12:%.*]] = zext i16 [[TMP12]] to i32 +; CHECK-NEXT: [[ADD_12:%.*]] = add i32 [[ADD_11]], [[CONV_12]] +; CHECK-NEXT: [[MUL_12:%.*]] = mul nuw nsw i32 [[CONV_12]], [[CONV_12]] +; CHECK-NEXT: [[ADD11_12:%.*]] = add i32 [[MUL_12]], [[ADD11_11]] +; CHECK-NEXT: [[ARRAYIDX_13:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 13 +; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[ARRAYIDX_13]], align 2 +; CHECK-NEXT: [[CONV_13:%.*]] = zext i16 [[TMP13]] to i32 +; CHECK-NEXT: [[ADD_13:%.*]] = add i32 [[ADD_12]], [[CONV_13]] +; CHECK-NEXT: [[MUL_13:%.*]] = mul nuw nsw i32 [[CONV_13]], [[CONV_13]] +; CHECK-NEXT: [[ADD11_13:%.*]] = add i32 [[MUL_13]], [[ADD11_12]] +; CHECK-NEXT: [[ARRAYIDX_14:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 14 +; CHECK-NEXT: [[TMP14:%.*]] = load i16, ptr [[ARRAYIDX_14]], align 2 +; CHECK-NEXT: [[CONV_14:%.*]] = zext i16 [[TMP14]] to i32 +; CHECK-NEXT: [[ADD_14:%.*]] = add i32 [[ADD_13]], [[CONV_14]] +; CHECK-NEXT: [[MUL_14:%.*]] = mul nuw nsw i32 [[CONV_14]], [[CONV_14]] +; CHECK-NEXT: [[ADD11_14:%.*]] = add i32 [[MUL_14]], [[ADD11_13]] +; CHECK-NEXT: [[ARRAYIDX_15:%.*]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 15 +; CHECK-NEXT: [[TMP15:%.*]] = load i16, ptr [[ARRAYIDX_15]], align 2 +; CHECK-NEXT: [[CONV_15:%.*]] = zext i16 [[TMP15]] to i32 +; CHECK-NEXT: [[OP_RDX1]] = add i32 [[ADD_14]], [[CONV_15]] +; CHECK-NEXT: [[MUL_15:%.*]] = mul nuw nsw i32 [[CONV_15]], [[CONV_15]] +; CHECK-NEXT: [[OP_RDX]] = add i32 [[MUL_15]], [[ADD11_14]] ; CHECK-NEXT: [[ADD_PTR]] = getelementptr inbounds i16, ptr [[P_ADDR_035]], i64 [[IDX_EXT]] ; CHECK-NEXT: [[INC13]] = add nuw nsw i32 [[Y_038]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC13]], 16 diff --git a/llvm/test/Transforms/SLPVectorizer/phi-node-bitwidt-op-not.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/phi-node-bitwidt-op-not.ll similarity index 94% rename from llvm/test/Transforms/SLPVectorizer/phi-node-bitwidt-op-not.ll rename to llvm/test/Transforms/SLPVectorizer/AArch64/phi-node-bitwidt-op-not.ll index 4478eab7b827a..15f4cffe77910 100644 --- a/llvm/test/Transforms/SLPVectorizer/phi-node-bitwidt-op-not.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/phi-node-bitwidt-op-not.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: %if x86-registered-target %{ opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s %} -; RUN: %if aarch64-registered-target %{ opt -S -passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s %} +; RUN: opt -S -passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s define i32 @test(ptr %b, ptr %c, i32 %0, ptr %a, i1 %tobool3.not) { ; CHECK-LABEL: define i32 @test( diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/splat-loads.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/splat-loads.ll index afaf6b98e5081..094d60b66b393 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/splat-loads.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/splat-loads.ll @@ -90,14 +90,14 @@ entry: define void @splat_loads_i64(ptr %array1, ptr %array2, ptr %ptrA, ptr %ptrB) { ; CHECK-LABEL: @splat_loads_i64( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[GEP_2_1:%.*]] = getelementptr inbounds i64, ptr [[ARRAY2:%.*]], i64 1 -; CHECK-NEXT: [[LD_2_0:%.*]] = load i64, ptr [[ARRAY2]], align 8 -; CHECK-NEXT: [[LD_2_1:%.*]] = load i64, ptr [[GEP_2_1]], align 8 +; CHECK-NEXT: [[GEP_2_2:%.*]] = getelementptr inbounds i64, ptr [[ARRAY3:%.*]], i64 1 +; CHECK-NEXT: [[LD_2_2:%.*]] = load i64, ptr [[ARRAY3]], align 8 +; CHECK-NEXT: [[LD_2_3:%.*]] = load i64, ptr [[GEP_2_2]], align 8 ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[ARRAY1:%.*]], align 8 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i64> poison, i64 [[LD_2_0]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i64> poison, i64 [[LD_2_2]], i32 0 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i64> [[TMP0]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> poison, i64 [[LD_2_1]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> poison, i64 [[LD_2_3]], i32 0 ; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i64> [[TMP4]], <2 x i64> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP6:%.*]] = or <2 x i64> [[TMP0]], [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = add <2 x i64> [[TMP3]], [[TMP6]] @@ -131,14 +131,14 @@ entry: define void @splat_loads_i32(ptr %array1, ptr %array2, ptr %ptrA, ptr %ptrB) { ; CHECK-LABEL: @splat_loads_i32( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[GEP_2_1:%.*]] = getelementptr inbounds i32, ptr [[ARRAY2:%.*]], i64 1 -; CHECK-NEXT: [[LD_2_0:%.*]] = load i32, ptr [[ARRAY2]], align 8 -; CHECK-NEXT: [[LD_2_1:%.*]] = load i32, ptr [[GEP_2_1]], align 8 +; CHECK-NEXT: [[GEP_2_2:%.*]] = getelementptr inbounds i32, ptr [[ARRAY3:%.*]], i64 1 +; CHECK-NEXT: [[LD_2_2:%.*]] = load i32, ptr [[ARRAY3]], align 8 +; CHECK-NEXT: [[LD_2_3:%.*]] = load i32, ptr [[GEP_2_2]], align 8 ; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[ARRAY1:%.*]], align 8 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> poison, i32 [[LD_2_0]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> poison, i32 [[LD_2_2]], i32 0 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i32> [[TMP0]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> poison, i32 [[LD_2_1]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> poison, i32 [[LD_2_3]], i32 0 ; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP6:%.*]] = or <2 x i32> [[TMP0]], [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = add <2 x i32> [[TMP3]], [[TMP6]] diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/unreachable-blocks-with-phis.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/unreachable-blocks-with-phis.ll index aeb82d800a2f7..3c2f9e4d0ab5d 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/unreachable-blocks-with-phis.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/unreachable-blocks-with-phis.ll @@ -4,17 +4,17 @@ define void @test() { ; CHECK-LABEL: define void @test() { ; CHECK-NEXT: [[ENTRY:.*]]: -; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr null, align 1 +; CHECK-NEXT: [[G_2197_REAL32_PRE:%.*]] = load i32, ptr null, align 1 +; CHECK-NEXT: [[G_2197_IMAG33_PRE:%.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr null, i32 0, i32 1), align 1 ; CHECK-NEXT: br label %[[IF_END:.*]] ; CHECK: [[IF_THEN:.*]]: ; CHECK-NEXT: br label %[[IF_END]] ; CHECK: [[IF_END]]: -; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP0]], %[[ENTRY]] ], [ poison, %[[IF_THEN]] ] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x i32> [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[G_2197_IMAG33_PRE]], %[[ENTRY]] ], [ 0, %[[IF_THEN]] ] +; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[G_2197_REAL32_PRE]], %[[ENTRY]] ], [ 0, %[[IF_THEN]] ] ; CHECK-NEXT: store i32 [[TMP2]], ptr null, align 1 ; CHECK-NEXT: br label %[[TRAP:.*]] ; CHECK: [[BB3:.*:]] -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i32> [[TMP1]], i32 1 ; CHECK-NEXT: store i32 [[TMP4]], ptr null, align 1 ; CHECK-NEXT: ret void ; CHECK: [[TRAP]]: diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/vector-getelementptr.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/vector-getelementptr.ll index 3cb81b72d26a1..14ce08cb7aebe 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/vector-getelementptr.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/vector-getelementptr.ll @@ -6,19 +6,36 @@ define void @should_vectorize_gep(ptr %base1, ptr %base2, ptr %base_gep) { ; CHECK-LABEL: define void @should_vectorize_gep ; CHECK-SAME: (ptr [[BASE1:%.*]], ptr [[BASE2:%.*]], ptr [[BASE_GEP:%.*]]) { ; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[BASE1]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i32> [[TMP0]] to <4 x i64> -; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[BASE2]], align 2 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i32> [[TMP2]] to <4 x i64> -; CHECK-NEXT: [[TMP4:%.*]] = sub <4 x i64> [[TMP1]], [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i64> [[TMP4]], i32 0 -; CHECK-NEXT: [[GETELEMENTPTR_RES_1:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i64> [[TMP4]], i32 1 -; CHECK-NEXT: [[GETELEMENTPTR_RES_2:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i64> [[TMP4]], i32 2 -; CHECK-NEXT: [[GETELEMENTPTR_RES_3:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i64> [[TMP4]], i32 3 -; CHECK-NEXT: [[GETELEMENTPTR_RES_4:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[TMP8]] +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[BASE1]], align 2 +; CHECK-NEXT: [[ZEXT1:%.*]] = zext i32 [[LOAD1]] to i64 +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[BASE2]], align 2 +; CHECK-NEXT: [[ZEXT2:%.*]] = zext i32 [[LOAD2]] to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[ZEXT1]], [[ZEXT2]] +; CHECK-NEXT: [[GETELEMENTPTR_RES_1:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[SUB]] +; CHECK-NEXT: [[GETELEMENTPTR1:%.*]] = getelementptr i32, ptr [[BASE1]], i64 1 +; CHECK-NEXT: [[GETELEMENTPTR2:%.*]] = getelementptr i32, ptr [[BASE2]], i64 1 +; CHECK-NEXT: [[LOAD3:%.*]] = load i32, ptr [[GETELEMENTPTR1]], align 2 +; CHECK-NEXT: [[ZEXT3:%.*]] = zext i32 [[LOAD3]] to i64 +; CHECK-NEXT: [[LOAD4:%.*]] = load i32, ptr [[GETELEMENTPTR2]], align 2 +; CHECK-NEXT: [[ZEXT4:%.*]] = zext i32 [[LOAD4]] to i64 +; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[ZEXT3]], [[ZEXT4]] +; CHECK-NEXT: [[GETELEMENTPTR_RES_2:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[SUB2]] +; CHECK-NEXT: [[GETELEMENTPTR3:%.*]] = getelementptr i32, ptr [[BASE1]], i64 2 +; CHECK-NEXT: [[GETELEMENTPTR4:%.*]] = getelementptr i32, ptr [[BASE2]], i64 2 +; CHECK-NEXT: [[LOAD5:%.*]] = load i32, ptr [[GETELEMENTPTR3]], align 2 +; CHECK-NEXT: [[ZEXT5:%.*]] = zext i32 [[LOAD5]] to i64 +; CHECK-NEXT: [[LOAD6:%.*]] = load i32, ptr [[GETELEMENTPTR4]], align 2 +; CHECK-NEXT: [[ZEXT6:%.*]] = zext i32 [[LOAD6]] to i64 +; CHECK-NEXT: [[SUB3:%.*]] = sub i64 [[ZEXT5]], [[ZEXT6]] +; CHECK-NEXT: [[GETELEMENTPTR_RES_3:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[SUB3]] +; CHECK-NEXT: [[GETELEMENTPTR5:%.*]] = getelementptr i32, ptr [[BASE1]], i64 3 +; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr [[BASE2]], i64 3 +; CHECK-NEXT: [[LOAD7:%.*]] = load i32, ptr [[GETELEMENTPTR5]], align 2 +; CHECK-NEXT: [[ZEXT7:%.*]] = zext i32 [[LOAD7]] to i64 +; CHECK-NEXT: [[LOAD8:%.*]] = load i32, ptr [[GETELEMENTPTR6]], align 2 +; CHECK-NEXT: [[ZEXT8:%.*]] = zext i32 [[LOAD8]] to i64 +; CHECK-NEXT: [[SUB4:%.*]] = sub i64 [[ZEXT7]], [[ZEXT8]] +; CHECK-NEXT: [[GETELEMENTPTR_RES_4:%.*]] = getelementptr i32, ptr [[BASE_GEP]], i64 [[SUB4]] ; CHECK-NEXT: call void @use_4(ptr [[GETELEMENTPTR_RES_1]], ptr [[GETELEMENTPTR_RES_2]], ptr [[GETELEMENTPTR_RES_3]], ptr [[GETELEMENTPTR_RES_4]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/vectorizable-selects-uniform-cmps.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/vectorizable-selects-uniform-cmps.ll index c728572313d77..cbf8bc9dcf8f8 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/vectorizable-selects-uniform-cmps.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/vectorizable-selects-uniform-cmps.ll @@ -249,7 +249,7 @@ define void @select_uniform_ugt_16xi8(ptr %ptr, i8 %x) { ; CHECK-NEXT: [[L_11:%.*]] = load i8, ptr [[GEP_11]], align 1 ; CHECK-NEXT: [[GEP_12:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i8 12 ; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[PTR]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <8 x i8> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[PTR]], align 1 ; CHECK-NEXT: [[S_8:%.*]] = select i1 [[CMP_8]], i8 [[TMP1]], i8 [[X:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[GEP_9]], align 1 ; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i8>, ptr [[GEP_12]], align 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/extract-subvector-long-input.ll b/llvm/test/Transforms/SLPVectorizer/X86/extract-subvector-long-input.ll new file mode 100644 index 0000000000000..f90456297d7cb --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/extract-subvector-long-input.ll @@ -0,0 +1,86 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=slp-vectorizer -S -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test() { +; CHECK-LABEL: define void @test() { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[PHI7:%.*]] = phi i32 [ 0, [[BB10:%.*]] ], [ 0, [[BB:%.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = phi <8 x i32> [ poison, [[BB10]] ], [ zeroinitializer, [[BB]] ] +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> , i32 [[PHI7]], i32 0 +; CHECK-NEXT: switch i32 0, label [[BB16:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB14:%.*]] +; CHECK-NEXT: i32 1, label [[BB11:%.*]] +; CHECK-NEXT: ] +; CHECK: bb9: +; CHECK-NEXT: br label [[BB11]] +; CHECK: bb10: +; CHECK-NEXT: br label [[BB1]] +; CHECK: bb11: +; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x i32> [ poison, [[BB9:%.*]] ], [ [[TMP1]], [[BB1]] ] +; CHECK-NEXT: ret void +; CHECK: bb14: +; CHECK-NEXT: ret void +; CHECK: bb15: +; CHECK-NEXT: ret void +; CHECK: bb16: +; CHECK-NEXT: [[TMP3:%.*]] = phi <8 x i32> [ [[TMP0]], [[BB1]] ], [ poison, [[BB25:%.*]] ] +; CHECK-NEXT: ret void +; CHECK: bb25: +; CHECK-NEXT: switch i32 0, label [[BB16]] [ +; CHECK-NEXT: i32 0, label [[BB14]] +; CHECK-NEXT: i32 1, label [[BB15:%.*]] +; CHECK-NEXT: ] +; +bb: + br label %bb1 + +bb1: + %phi = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi2 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi3 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi4 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi5 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi6 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi7 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + %phi8 = phi i32 [ 0, %bb10 ], [ 0, %bb ] + switch i32 0, label %bb16 [ + i32 0, label %bb14 + i32 1, label %bb11 + ] + +bb9: + br label %bb11 + +bb10: + br label %bb1 + +bb11: + %phi12 = phi i32 [ 0, %bb9 ], [ %phi7, %bb1 ] + %phi13 = phi i32 [ 0, %bb9 ], [ undef, %bb1 ] + ret void + +bb14: + ret void + +bb15: + ret void + +bb16: + %phi17 = phi i32 [ %phi, %bb1 ], [ 0, %bb25 ] + %phi18 = phi i32 [ %phi2, %bb1 ], [ 0, %bb25 ] + %phi19 = phi i32 [ %phi3, %bb1 ], [ 0, %bb25 ] + %phi20 = phi i32 [ %phi4, %bb1 ], [ 0, %bb25 ] + %phi21 = phi i32 [ %phi5, %bb1 ], [ 0, %bb25 ] + %phi22 = phi i32 [ %phi6, %bb1 ], [ 0, %bb25 ] + %phi23 = phi i32 [ %phi7, %bb1 ], [ 0, %bb25 ] + %phi24 = phi i32 [ %phi8, %bb1 ], [ 0, %bb25 ] + ret void + +bb25: + switch i32 0, label %bb16 [ + i32 0, label %bb14 + i32 1, label %bb15 + ] +} diff --git a/llvm/test/Transforms/SLPVectorizer/icmp-altopcode-after-reordering.ll b/llvm/test/Transforms/SLPVectorizer/X86/icmp-altopcode-after-reordering.ll similarity index 91% rename from llvm/test/Transforms/SLPVectorizer/icmp-altopcode-after-reordering.ll rename to llvm/test/Transforms/SLPVectorizer/X86/icmp-altopcode-after-reordering.ll index 002b9a70255da..278e55c67f23f 100644 --- a/llvm/test/Transforms/SLPVectorizer/icmp-altopcode-after-reordering.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/icmp-altopcode-after-reordering.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: %if x86-registered-target %{ opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s %} -; RUN: %if aarch64-registered-target %{ opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s %} +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s define i32 @test(ptr %sptr, i64 %0) { ; CHECK-LABEL: define i32 @test( diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll new file mode 100644 index 0000000000000..0dac02b0bcc09 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define i32 @test(ptr %b, ptr %c, i32 %0, ptr %a, i1 %tobool3.not) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[B:%.*]], ptr [[C:%.*]], i32 [[TMP0:%.*]], ptr [[A:%.*]], i1 [[TOBOOL3_NOT:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[TOBOOL3_NOT]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = ashr <4 x i32> [[TMP2]], splat (i32 16) +; CHECK-NEXT: [[TMP4:%.*]] = icmp slt <4 x i32> [[TMP3]], [[TMP2]] +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i16> +; CHECK-NEXT: br label [[BB3:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt <4 x i32> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = zext <4 x i1> [[TMP8]] to <4 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x i1> poison, i1 [[TOBOOL3_NOT]], i32 0 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i1> [[TMP10]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[TMP11]], <4 x i32> [[TMP7]], <4 x i32> [[TMP9]] +; CHECK-NEXT: [[TMP13:%.*]] = shl <4 x i32> [[TMP12]], splat (i32 16) +; CHECK-NEXT: [[TMP14:%.*]] = ashr <4 x i32> [[TMP13]], splat (i32 16) +; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16> +; CHECK-NEXT: br i1 true, label [[BB3]], label [[BB2]] +; CHECK: bb3: +; CHECK-NEXT: [[TMP16:%.*]] = phi <4 x i16> [ [[TMP5]], [[BB1]] ], [ [[TMP15]], [[BB2]] ] +; CHECK-NEXT: [[TMP17:%.*]] = extractelement <4 x i16> [[TMP16]], i32 0 +; CHECK-NEXT: [[TMP18:%.*]] = sext i16 [[TMP17]] to i32 +; CHECK-NEXT: store i32 [[TMP18]], ptr [[B]], align 16 +; CHECK-NEXT: [[TMP19:%.*]] = extractelement <4 x i16> [[TMP16]], i32 1 +; CHECK-NEXT: [[TMP20:%.*]] = sext i16 [[TMP19]] to i32 +; CHECK-NEXT: store i32 [[TMP20]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP21:%.*]] = extractelement <4 x i16> [[TMP16]], i32 2 +; CHECK-NEXT: [[TMP22:%.*]] = sext i16 [[TMP21]] to i32 +; CHECK-NEXT: store i32 [[TMP22]], ptr [[C]], align 16 +; CHECK-NEXT: [[TMP23:%.*]] = extractelement <4 x i16> [[TMP16]], i32 3 +; CHECK-NEXT: [[TMP24:%.*]] = sext i16 [[TMP23]] to i32 +; CHECK-NEXT: store i32 [[TMP24]], ptr [[B]], align 8 +; CHECK-NEXT: ret i32 0 +; +entry: + br i1 %tobool3.not, label %bb1, label %bb2 + +bb1: + %conv1.i.us = ashr i32 %0, 16 + %cmp2.i.us = icmp slt i32 %conv1.i.us, %0 + %sext26.us = zext i1 %cmp2.i.us to i32 + %conv1.i.us.5 = ashr i32 %0, 16 + %cmp2.i.us.5 = icmp slt i32 %conv1.i.us.5, %0 + %sext26.us.5 = zext i1 %cmp2.i.us.5 to i32 + %conv1.i.us.6 = ashr i32 %0, 16 + %cmp2.i.us.6 = icmp slt i32 %conv1.i.us.6, %0 + %sext26.us.6 = zext i1 %cmp2.i.us.6 to i32 + %conv1.i.us.7 = ashr i32 %0, 16 + %cmp2.i.us.7 = icmp slt i32 %conv1.i.us.7, %0 + %sext26.us.7 = zext i1 %cmp2.i.us.7 to i32 + br label %bb3 + +bb2: + %cmp2.i = icmp sgt i32 %0, 0 + %1 = zext i1 %cmp2.i to i32 + %cond.i = select i1 %tobool3.not, i32 %0, i32 %1 + %sext26 = shl i32 %cond.i, 16 + %conv13 = ashr i32 %sext26, 16 + %cmp2.i.5 = icmp sgt i32 %0, 0 + %2 = zext i1 %cmp2.i.5 to i32 + %cond.i.5 = select i1 %tobool3.not, i32 %0, i32 %2 + %sext26.5 = shl i32 %cond.i.5, 16 + %conv13.5 = ashr i32 %sext26.5, 16 + %cmp2.i.6 = icmp sgt i32 %0, 0 + %3 = zext i1 %cmp2.i.6 to i32 + %cond.i.6 = select i1 %tobool3.not, i32 %0, i32 %3 + %sext26.6 = shl i32 %cond.i.6, 16 + %conv13.6 = ashr i32 %sext26.6, 16 + %cmp2.i.7 = icmp sgt i32 %0, 0 + %4 = zext i1 %cmp2.i.7 to i32 + %cond.i.7 = select i1 %tobool3.not, i32 %0, i32 %4 + %sext26.7 = shl i32 %cond.i.7, 16 + %conv13.7 = ashr i32 %sext26.7, 16 + br i1 true, label %bb3, label %bb2 + +bb3: + %conv13p = phi i32 [ %sext26.us, %bb1 ], [ %conv13, %bb2 ] + %conv13.5p = phi i32 [ %sext26.us.5, %bb1 ], [ %conv13.5, %bb2 ] + %conv13.6p = phi i32 [ %sext26.us.6, %bb1 ], [ %conv13.6, %bb2 ] + %conv13.7p = phi i32 [ %sext26.us.7, %bb1 ], [ %conv13.7, %bb2 ] + store i32 %conv13p, ptr %b, align 16 + store i32 %conv13.5p, ptr %a, align 8 + store i32 %conv13.6p, ptr %c, align 16 + store i32 %conv13.7p, ptr %b, align 8 + ret i32 0 +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/revectorize-phis.ll b/llvm/test/Transforms/SLPVectorizer/X86/revectorize-phis.ll new file mode 100644 index 0000000000000..9eec3074b5345 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/revectorize-phis.ll @@ -0,0 +1,193 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test() { +; CHECK-LABEL: define void @test() { +; CHECK-NEXT: [[BB:.*]]: +; CHECK-NEXT: br label %[[BB1:.*]] +; CHECK: [[BB1]]: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI]], %[[BB31:.*]] ], [ [[PHI]], %[[BB32:.*]] ], [ [[PHI]], %[[BB33:.*]] ], [ [[PHI]], %[[BB36:.*]] ], [ [[PHI]], %[[BB39:.*]] ], [ [[PHI]], %[[BB40:.*]] ], [ [[PHI]], %[[BB41:.*]] ], [ [[PHI]], %[[BB42:.*]] ], [ [[PHI]], %[[BB43:.*]] ], [ 0, %[[BB45:.*]] ], [ [[PHI]], %[[BB21:.*]] ], [ [[PHI]], %[[BB22:.*]] ], [ [[PHI]], %[[BB23:.*]] ], [ [[PHI]], %[[BB24:.*]] ], [ [[PHI]], %[[BB25:.*]] ], [ [[PHI]], %[[BB26:.*]] ], [ [[PHI]], %[[BB27:.*]] ], [ [[PHI]], %[[BB28:.*]] ], [ [[PHI]], %[[BB29:.*]] ], [ 0, %[[BB30:.*]] ] +; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI2]], %[[BB31]] ], [ [[PHI2]], %[[BB32]] ], [ [[PHI2]], %[[BB33]] ], [ [[PHI2]], %[[BB36]] ], [ [[PHI2]], %[[BB39]] ], [ [[PHI2]], %[[BB40]] ], [ [[PHI2]], %[[BB41]] ], [ [[PHI2]], %[[BB42]] ], [ [[LOAD44:%.*]], %[[BB43]] ], [ [[PHI2]], %[[BB45]] ], [ [[PHI2]], %[[BB21]] ], [ 0, %[[BB22]] ], [ [[PHI2]], %[[BB23]] ], [ [[PHI2]], %[[BB24]] ], [ [[PHI2]], %[[BB25]] ], [ [[PHI2]], %[[BB26]] ], [ [[PHI2]], %[[BB27]] ], [ [[PHI2]], %[[BB28]] ], [ [[PHI2]], %[[BB29]] ], [ [[PHI2]], %[[BB30]] ] +; CHECK-NEXT: [[PHI3:%.*]] = phi i64 [ 0, %[[BB]] ], [ 0, %[[BB31]] ], [ [[PHI3]], %[[BB32]] ], [ [[PHI3]], %[[BB33]] ], [ [[PHI3]], %[[BB36]] ], [ [[PHI3]], %[[BB39]] ], [ [[PHI3]], %[[BB40]] ], [ [[PHI3]], %[[BB41]] ], [ 0, %[[BB42]] ], [ [[PHI3]], %[[BB43]] ], [ [[PHI3]], %[[BB45]] ], [ [[PHI3]], %[[BB21]] ], [ [[PHI3]], %[[BB22]] ], [ [[PHI3]], %[[BB23]] ], [ [[PHI3]], %[[BB24]] ], [ [[PHI3]], %[[BB25]] ], [ [[PHI3]], %[[BB26]] ], [ [[PHI3]], %[[BB27]] ], [ [[PHI3]], %[[BB28]] ], [ [[PHI3]], %[[BB29]] ], [ [[PHI3]], %[[BB30]] ] +; CHECK-NEXT: [[PHI4:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI4]], %[[BB31]] ], [ [[PHI4]], %[[BB32]] ], [ [[PHI4]], %[[BB33]] ], [ [[PHI4]], %[[BB36]] ], [ [[PHI4]], %[[BB39]] ], [ [[PHI4]], %[[BB40]] ], [ [[PHI4]], %[[BB41]] ], [ [[PHI4]], %[[BB42]] ], [ [[PHI4]], %[[BB43]] ], [ [[PHI4]], %[[BB45]] ], [ [[PHI4]], %[[BB21]] ], [ [[PHI4]], %[[BB22]] ], [ [[PHI4]], %[[BB23]] ], [ [[PHI4]], %[[BB24]] ], [ [[PHI4]], %[[BB25]] ], [ [[PHI4]], %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI4]], %[[BB28]] ], [ [[PHI4]], %[[BB29]] ], [ [[PHI4]], %[[BB30]] ] +; CHECK-NEXT: [[PHI5:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI5]], %[[BB31]] ], [ [[PHI5]], %[[BB32]] ], [ [[PHI5]], %[[BB33]] ], [ [[PHI5]], %[[BB36]] ], [ 0, %[[BB39]] ], [ [[PHI5]], %[[BB40]] ], [ [[PHI5]], %[[BB41]] ], [ [[PHI5]], %[[BB42]] ], [ [[PHI5]], %[[BB43]] ], [ [[PHI5]], %[[BB45]] ], [ 0, %[[BB21]] ], [ [[PHI5]], %[[BB22]] ], [ [[PHI5]], %[[BB23]] ], [ [[PHI5]], %[[BB24]] ], [ [[PHI5]], %[[BB25]] ], [ [[PHI5]], %[[BB26]] ], [ [[PHI5]], %[[BB27]] ], [ [[PHI5]], %[[BB28]] ], [ [[PHI5]], %[[BB29]] ], [ [[PHI5]], %[[BB30]] ] +; CHECK-NEXT: [[PHI6:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI6]], %[[BB31]] ], [ 0, %[[BB32]] ], [ 0, %[[BB33]] ], [ [[LOAD38:%.*]], %[[BB36]] ], [ 0, %[[BB39]] ], [ 0, %[[BB40]] ], [ [[PHI6]], %[[BB41]] ], [ [[PHI6]], %[[BB42]] ], [ [[PHI6]], %[[BB43]] ], [ [[PHI6]], %[[BB45]] ], [ [[PHI6]], %[[BB21]] ], [ 0, %[[BB22]] ], [ [[PHI6]], %[[BB23]] ], [ [[PHI6]], %[[BB24]] ], [ [[PHI6]], %[[BB25]] ], [ 0, %[[BB26]] ], [ [[PHI6]], %[[BB27]] ], [ [[PHI6]], %[[BB28]] ], [ [[PHI6]], %[[BB29]] ], [ [[PHI6]], %[[BB30]] ] +; CHECK-NEXT: [[PHI7:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI7]], %[[BB31]] ], [ [[PTRTOINT:%.*]], %[[BB32]] ], [ [[PHI7]], %[[BB33]] ], [ [[PHI7]], %[[BB36]] ], [ [[PHI7]], %[[BB39]] ], [ [[PHI7]], %[[BB40]] ], [ [[PHI7]], %[[BB41]] ], [ [[PHI7]], %[[BB42]] ], [ [[PHI7]], %[[BB43]] ], [ 0, %[[BB45]] ], [ [[PHI7]], %[[BB21]] ], [ [[PHI7]], %[[BB22]] ], [ [[PHI7]], %[[BB23]] ], [ [[PHI7]], %[[BB24]] ], [ [[PHI7]], %[[BB25]] ], [ [[PHI7]], %[[BB26]] ], [ [[PHI7]], %[[BB27]] ], [ [[PHI7]], %[[BB28]] ], [ [[PHI7]], %[[BB29]] ], [ [[PHI7]], %[[BB30]] ] +; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ 0, %[[BB]] ], [ 0, %[[BB31]] ], [ [[PHI8]], %[[BB32]] ], [ [[PHI8]], %[[BB33]] ], [ [[PHI8]], %[[BB36]] ], [ [[PHI8]], %[[BB39]] ], [ [[PHI8]], %[[BB40]] ], [ [[PHI8]], %[[BB41]] ], [ [[PHI8]], %[[BB42]] ], [ [[PHI8]], %[[BB43]] ], [ [[PHI8]], %[[BB45]] ], [ [[PHI8]], %[[BB21]] ], [ [[PHI8]], %[[BB22]] ], [ [[PHI8]], %[[BB23]] ], [ [[PHI8]], %[[BB24]] ], [ [[PHI8]], %[[BB25]] ], [ [[PHI8]], %[[BB26]] ], [ [[PHI8]], %[[BB27]] ], [ [[PHI8]], %[[BB28]] ], [ [[PHI8]], %[[BB29]] ], [ [[PHI8]], %[[BB30]] ] +; CHECK-NEXT: [[PHI9:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI9]], %[[BB31]] ], [ [[PHI9]], %[[BB32]] ], [ [[PHI9]], %[[BB33]] ], [ [[PHI9]], %[[BB36]] ], [ [[PHI9]], %[[BB39]] ], [ [[PHI9]], %[[BB40]] ], [ [[PHI9]], %[[BB41]] ], [ 0, %[[BB42]] ], [ [[PHI9]], %[[BB43]] ], [ [[LOAD46:%.*]], %[[BB45]] ], [ [[PHI9]], %[[BB21]] ], [ [[PHI9]], %[[BB22]] ], [ 0, %[[BB23]] ], [ [[PHI9]], %[[BB24]] ], [ [[PHI9]], %[[BB25]] ], [ [[PHI9]], %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI9]], %[[BB28]] ], [ [[PHI9]], %[[BB29]] ], [ [[PHI]], %[[BB30]] ] +; CHECK-NEXT: [[PHI10:%.*]] = phi i64 [ 0, %[[BB]] ], [ 0, %[[BB31]] ], [ [[PHI10]], %[[BB32]] ], [ [[PHI10]], %[[BB33]] ], [ [[PHI10]], %[[BB36]] ], [ 0, %[[BB39]] ], [ [[PHI10]], %[[BB40]] ], [ [[PHI10]], %[[BB41]] ], [ [[PHI10]], %[[BB42]] ], [ 0, %[[BB43]] ], [ [[PHI10]], %[[BB45]] ], [ [[PHI10]], %[[BB21]] ], [ [[PHI10]], %[[BB22]] ], [ [[PHI10]], %[[BB23]] ], [ 0, %[[BB24]] ], [ [[PHI10]], %[[BB25]] ], [ [[PHI10]], %[[BB26]] ], [ [[PHI10]], %[[BB27]] ], [ [[PHI10]], %[[BB28]] ], [ [[PHI2]], %[[BB29]] ], [ [[PHI10]], %[[BB30]] ] +; CHECK-NEXT: [[PHI11:%.*]] = phi i64 [ undef, %[[BB]] ], [ [[PHI11]], %[[BB31]] ], [ [[PHI11]], %[[BB32]] ], [ [[PHI11]], %[[BB33]] ], [ [[PHI11]], %[[BB36]] ], [ [[PHI11]], %[[BB39]] ], [ [[PHI11]], %[[BB40]] ], [ [[PHI11]], %[[BB41]] ], [ 0, %[[BB42]] ], [ 0, %[[BB43]] ], [ [[PHI11]], %[[BB45]] ], [ [[PHI11]], %[[BB21]] ], [ [[PHI11]], %[[BB22]] ], [ [[PHI11]], %[[BB23]] ], [ [[PHI11]], %[[BB24]] ], [ [[PHI11]], %[[BB25]] ], [ [[PHI11]], %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI3]], %[[BB28]] ], [ [[PHI11]], %[[BB29]] ], [ [[PHI11]], %[[BB30]] ] +; CHECK-NEXT: [[PHI12:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI12]], %[[BB31]] ], [ 0, %[[BB32]] ], [ [[PHI12]], %[[BB33]] ], [ [[LOAD37:%.*]], %[[BB36]] ], [ [[PHI12]], %[[BB39]] ], [ [[PHI12]], %[[BB40]] ], [ [[PHI12]], %[[BB41]] ], [ [[PHI12]], %[[BB42]] ], [ [[PHI12]], %[[BB43]] ], [ [[PHI12]], %[[BB45]] ], [ [[PHI12]], %[[BB21]] ], [ [[PHI12]], %[[BB22]] ], [ [[PHI12]], %[[BB23]] ], [ 1, %[[BB24]] ], [ [[PHI12]], %[[BB25]] ], [ 0, %[[BB26]] ], [ [[PHI12]], %[[BB27]] ], [ [[PHI12]], %[[BB28]] ], [ [[PHI12]], %[[BB29]] ], [ [[PHI12]], %[[BB30]] ] +; CHECK-NEXT: [[PHI13:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI13]], %[[BB31]] ], [ [[PHI13]], %[[BB32]] ], [ [[LOAD35:%.*]], %[[BB33]] ], [ [[PHI13]], %[[BB36]] ], [ [[PHI13]], %[[BB39]] ], [ [[PHI13]], %[[BB40]] ], [ [[PHI13]], %[[BB41]] ], [ 0, %[[BB42]] ], [ [[PHI13]], %[[BB43]] ], [ [[PHI13]], %[[BB45]] ], [ [[PHI13]], %[[BB21]] ], [ [[PHI13]], %[[BB22]] ], [ 0, %[[BB23]] ], [ 1, %[[BB24]] ], [ [[PHI13]], %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI13]], %[[BB28]] ], [ [[PHI13]], %[[BB29]] ], [ [[PHI13]], %[[BB30]] ] +; CHECK-NEXT: [[PHI14:%.*]] = phi i64 [ 0, %[[BB]] ], [ 0, %[[BB31]] ], [ [[PHI14]], %[[BB32]] ], [ [[LOAD34:%.*]], %[[BB33]] ], [ 0, %[[BB36]] ], [ [[PHI14]], %[[BB39]] ], [ [[PHI14]], %[[BB40]] ], [ [[PHI14]], %[[BB41]] ], [ [[PHI14]], %[[BB42]] ], [ [[PHI14]], %[[BB43]] ], [ [[PHI14]], %[[BB45]] ], [ [[PHI14]], %[[BB21]] ], [ [[PHI14]], %[[BB22]] ], [ 0, %[[BB23]] ], [ [[PHI14]], %[[BB24]] ], [ [[PHI14]], %[[BB25]] ], [ [[PHI14]], %[[BB26]] ], [ [[PHI14]], %[[BB27]] ], [ [[PHI14]], %[[BB28]] ], [ [[PHI14]], %[[BB29]] ], [ [[PHI14]], %[[BB30]] ] +; CHECK-NEXT: [[PHI15:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[LOAD:%.*]], %[[BB31]] ], [ [[PHI15]], %[[BB32]] ], [ [[PHI15]], %[[BB33]] ], [ [[PHI15]], %[[BB36]] ], [ 0, %[[BB39]] ], [ [[PHI15]], %[[BB40]] ], [ [[PHI15]], %[[BB41]] ], [ 0, %[[BB42]] ], [ [[PHI15]], %[[BB43]] ], [ [[PHI15]], %[[BB45]] ], [ [[PHI8]], %[[BB21]] ], [ [[PHI15]], %[[BB22]] ], [ [[PHI15]], %[[BB23]] ], [ [[PHI15]], %[[BB24]] ], [ [[PHI15]], %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI15]], %[[BB28]] ], [ [[PHI15]], %[[BB29]] ], [ [[PHI15]], %[[BB30]] ] +; CHECK-NEXT: [[PHI16:%.*]] = phi i8 [ 3, %[[BB]] ], [ 0, %[[BB31]] ], [ 0, %[[BB32]] ], [ 0, %[[BB33]] ], [ 0, %[[BB36]] ], [ 0, %[[BB39]] ], [ 0, %[[BB40]] ], [ 0, %[[BB41]] ], [ 0, %[[BB42]] ], [ 0, %[[BB43]] ], [ 0, %[[BB45]] ], [ 0, %[[BB21]] ], [ 0, %[[BB22]] ], [ 0, %[[BB23]] ], [ 0, %[[BB24]] ], [ 0, %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ 0, %[[BB28]] ], [ 0, %[[BB29]] ], [ 0, %[[BB30]] ] +; CHECK-NEXT: [[PHI17:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI17]], %[[BB31]] ], [ [[PHI17]], %[[BB32]] ], [ [[PHI17]], %[[BB33]] ], [ [[PHI17]], %[[BB36]] ], [ 0, %[[BB39]] ], [ [[PHI17]], %[[BB40]] ], [ [[PHI4]], %[[BB41]] ], [ [[PHI17]], %[[BB42]] ], [ 0, %[[BB43]] ], [ [[PHI17]], %[[BB45]] ], [ [[PHI17]], %[[BB21]] ], [ [[PHI17]], %[[BB22]] ], [ [[PHI17]], %[[BB23]] ], [ 0, %[[BB24]] ], [ [[PHI17]], %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI17]], %[[BB28]] ], [ [[PHI17]], %[[BB29]] ], [ [[PHI17]], %[[BB30]] ] +; CHECK-NEXT: [[PHI18:%.*]] = phi i8 [ 0, %[[BB]] ], [ 0, %[[BB31]] ], [ 0, %[[BB32]] ], [ 0, %[[BB33]] ], [ 0, %[[BB36]] ], [ 0, %[[BB39]] ], [ 0, %[[BB40]] ], [ 0, %[[BB41]] ], [ 0, %[[BB42]] ], [ 0, %[[BB43]] ], [ 0, %[[BB45]] ], [ 0, %[[BB21]] ], [ 0, %[[BB22]] ], [ 0, %[[BB23]] ], [ 0, %[[BB24]] ], [ 0, %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ 0, %[[BB28]] ], [ 0, %[[BB29]] ], [ 0, %[[BB30]] ] +; CHECK-NEXT: [[PHI19:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI19]], %[[BB31]] ], [ [[PHI19]], %[[BB32]] ], [ [[PHI19]], %[[BB33]] ], [ [[PHI19]], %[[BB36]] ], [ 0, %[[BB39]] ], [ [[PHI19]], %[[BB40]] ], [ [[PHI19]], %[[BB41]] ], [ [[PHI19]], %[[BB42]] ], [ 0, %[[BB43]] ], [ [[PHI19]], %[[BB45]] ], [ [[PHI19]], %[[BB21]] ], [ [[PHI19]], %[[BB22]] ], [ [[PHI19]], %[[BB23]] ], [ [[PHI19]], %[[BB24]] ], [ [[PHI5]], %[[BB25]] ], [ 0, %[[BB26]] ], [ 0, %[[BB27]] ], [ [[PHI19]], %[[BB28]] ], [ [[PHI19]], %[[BB29]] ], [ [[PHI19]], %[[BB30]] ] +; CHECK-NEXT: [[PHI20:%.*]] = phi i64 [ 0, %[[BB]] ], [ [[PHI20]], %[[BB31]] ], [ [[PTRTOINT]], %[[BB32]] ], [ [[PHI20]], %[[BB33]] ], [ [[PHI20]], %[[BB36]] ], [ [[PHI20]], %[[BB39]] ], [ 0, %[[BB40]] ], [ [[PHI20]], %[[BB41]] ], [ 0, %[[BB42]] ], [ [[PHI20]], %[[BB43]] ], [ [[PHI20]], %[[BB45]] ], [ [[PHI20]], %[[BB21]] ], [ [[PHI7]], %[[BB22]] ], [ [[PHI20]], %[[BB23]] ], [ [[PHI20]], %[[BB24]] ], [ [[PHI20]], %[[BB25]] ], [ 0, %[[BB26]] ], [ [[PHI20]], %[[BB27]] ], [ [[PHI20]], %[[BB28]] ], [ [[PHI20]], %[[BB29]] ], [ [[PHI20]], %[[BB30]] ] +; CHECK-NEXT: switch i8 0, label %[[BB30]] [ +; CHECK-NEXT: i8 9, label %[[BB26]] +; CHECK-NEXT: i8 0, label %[[BB29]] +; CHECK-NEXT: i8 13, label %[[BB28]] +; CHECK-NEXT: i8 1, label %[[BB21]] +; CHECK-NEXT: i8 3, label %[[BB22]] +; CHECK-NEXT: i8 12, label %[[BB27]] +; CHECK-NEXT: i8 5, label %[[BB23]] +; CHECK-NEXT: i8 6, label %[[BB24]] +; CHECK-NEXT: i8 7, label %[[BB25]] +; CHECK-NEXT: ] +; CHECK: [[BB21]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB31]] +; CHECK: [[BB22]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB32]] +; CHECK: [[BB23]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB33]] +; CHECK: [[BB24]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB36]] +; CHECK: [[BB25]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB39]] +; CHECK: [[BB26]]: +; CHECK-NEXT: br i1 false, label %[[BB40]], label %[[BB1]] +; CHECK: [[BB27]]: +; CHECK-NEXT: br i1 false, label %[[BB41]], label %[[BB1]] +; CHECK: [[BB28]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB42]] +; CHECK: [[BB29]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB43]] +; CHECK: [[BB30]]: +; CHECK-NEXT: br i1 false, label %[[BB1]], label %[[BB45]] +; CHECK: [[BB31]]: +; CHECK-NEXT: [[LOAD]] = load i64, ptr null, align 8 +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB32]]: +; CHECK-NEXT: [[PTRTOINT]] = ptrtoint ptr null to i64 +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB33]]: +; CHECK-NEXT: [[LOAD34]] = load i64, ptr null, align 8 +; CHECK-NEXT: [[LOAD35]] = load i64, ptr null, align 8 +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB36]]: +; CHECK-NEXT: [[LOAD37]] = load i64, ptr null, align 8 +; CHECK-NEXT: [[LOAD38]] = load i64, ptr null, align 8 +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB39]]: +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB40]]: +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB41]]: +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB42]]: +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB43]]: +; CHECK-NEXT: [[LOAD44]] = load i64, ptr null, align 8 +; CHECK-NEXT: br label %[[BB1]] +; CHECK: [[BB45]]: +; CHECK-NEXT: [[LOAD46]] = load i64, ptr null, align 8 +; CHECK-NEXT: br label %[[BB1]] +; +bb: + br label %bb1 + +bb1: + %phi = phi i64 [ 0, %bb ], [ %phi, %bb31 ], [ %phi, %bb32 ], [ %phi, %bb33 ], [ %phi, %bb36 ], [ %phi, %bb39 ], [ %phi, %bb40 ], [ %phi, %bb41 ], [ %phi, %bb42 ], [ %phi, %bb43 ], [ 0, %bb45 ], [ %phi, %bb21 ], [ %phi, %bb22 ], [ %phi, %bb23 ], [ %phi, %bb24 ], [ %phi, %bb25 ], [ %phi, %bb26 ], [ %phi, %bb27 ], [ %phi, %bb28 ], [ %phi, %bb29 ], [ 0, %bb30 ] + %phi2 = phi i64 [ undef, %bb ], [ %phi2, %bb31 ], [ %phi2, %bb32 ], [ %phi2, %bb33 ], [ %phi2, %bb36 ], [ %phi2, %bb39 ], [ %phi2, %bb40 ], [ %phi2, %bb41 ], [ %phi2, %bb42 ], [ %load44, %bb43 ], [ %phi2, %bb45 ], [ %phi2, %bb21 ], [ 0, %bb22 ], [ %phi2, %bb23 ], [ %phi2, %bb24 ], [ %phi2, %bb25 ], [ %phi2, %bb26 ], [ %phi2, %bb27 ], [ %phi2, %bb28 ], [ %phi2, %bb29 ], [ %phi2, %bb30 ] + %phi3 = phi i64 [ 0, %bb ], [ 0, %bb31 ], [ %phi3, %bb32 ], [ %phi3, %bb33 ], [ %phi3, %bb36 ], [ %phi3, %bb39 ], [ %phi3, %bb40 ], [ %phi3, %bb41 ], [ 0, %bb42 ], [ %phi3, %bb43 ], [ %phi3, %bb45 ], [ %phi3, %bb21 ], [ %phi3, %bb22 ], [ %phi3, %bb23 ], [ %phi3, %bb24 ], [ %phi3, %bb25 ], [ %phi3, %bb26 ], [ %phi3, %bb27 ], [ %phi3, %bb28 ], [ %phi3, %bb29 ], [ %phi3, %bb30 ] + %phi4 = phi i64 [ 0, %bb ], [ %phi4, %bb31 ], [ %phi4, %bb32 ], [ %phi4, %bb33 ], [ %phi4, %bb36 ], [ %phi4, %bb39 ], [ %phi4, %bb40 ], [ %phi4, %bb41 ], [ %phi4, %bb42 ], [ %phi4, %bb43 ], [ %phi4, %bb45 ], [ %phi4, %bb21 ], [ %phi4, %bb22 ], [ %phi4, %bb23 ], [ %phi4, %bb24 ], [ %phi4, %bb25 ], [ %phi4, %bb26 ], [ 0, %bb27 ], [ %phi4, %bb28 ], [ %phi4, %bb29 ], [ %phi4, %bb30 ] + %phi5 = phi i64 [ undef, %bb ], [ %phi5, %bb31 ], [ %phi5, %bb32 ], [ %phi5, %bb33 ], [ %phi5, %bb36 ], [ 0, %bb39 ], [ %phi5, %bb40 ], [ %phi5, %bb41 ], [ %phi5, %bb42 ], [ %phi5, %bb43 ], [ %phi5, %bb45 ], [ 0, %bb21 ], [ %phi5, %bb22 ], [ %phi5, %bb23 ], [ %phi5, %bb24 ], [ %phi5, %bb25 ], [ %phi5, %bb26 ], [ %phi5, %bb27 ], [ %phi5, %bb28 ], [ %phi5, %bb29 ], [ %phi5, %bb30 ] + %phi6 = phi i64 [ undef, %bb ], [ %phi6, %bb31 ], [ 0, %bb32 ], [ 0, %bb33 ], [ %load38, %bb36 ], [ 0, %bb39 ], [ 0, %bb40 ], [ %phi6, %bb41 ], [ %phi6, %bb42 ], [ %phi6, %bb43 ], [ %phi6, %bb45 ], [ %phi6, %bb21 ], [ 0, %bb22 ], [ %phi6, %bb23 ], [ %phi6, %bb24 ], [ %phi6, %bb25 ], [ 0, %bb26 ], [ %phi6, %bb27 ], [ %phi6, %bb28 ], [ %phi6, %bb29 ], [ %phi6, %bb30 ] + %phi7 = phi i64 [ undef, %bb ], [ %phi7, %bb31 ], [ %ptrtoint, %bb32 ], [ %phi7, %bb33 ], [ %phi7, %bb36 ], [ %phi7, %bb39 ], [ %phi7, %bb40 ], [ %phi7, %bb41 ], [ %phi7, %bb42 ], [ %phi7, %bb43 ], [ 0, %bb45 ], [ %phi7, %bb21 ], [ %phi7, %bb22 ], [ %phi7, %bb23 ], [ %phi7, %bb24 ], [ %phi7, %bb25 ], [ %phi7, %bb26 ], [ %phi7, %bb27 ], [ %phi7, %bb28 ], [ %phi7, %bb29 ], [ %phi7, %bb30 ] + %phi8 = phi i64 [ 0, %bb ], [ 0, %bb31 ], [ %phi8, %bb32 ], [ %phi8, %bb33 ], [ %phi8, %bb36 ], [ %phi8, %bb39 ], [ %phi8, %bb40 ], [ %phi8, %bb41 ], [ %phi8, %bb42 ], [ %phi8, %bb43 ], [ %phi8, %bb45 ], [ %phi8, %bb21 ], [ %phi8, %bb22 ], [ %phi8, %bb23 ], [ %phi8, %bb24 ], [ %phi8, %bb25 ], [ %phi8, %bb26 ], [ %phi8, %bb27 ], [ %phi8, %bb28 ], [ %phi8, %bb29 ], [ %phi8, %bb30 ] + %phi9 = phi i64 [ undef, %bb ], [ %phi9, %bb31 ], [ %phi9, %bb32 ], [ %phi9, %bb33 ], [ %phi9, %bb36 ], [ %phi9, %bb39 ], [ %phi9, %bb40 ], [ %phi9, %bb41 ], [ 0, %bb42 ], [ %phi9, %bb43 ], [ %load46, %bb45 ], [ %phi9, %bb21 ], [ %phi9, %bb22 ], [ 0, %bb23 ], [ %phi9, %bb24 ], [ %phi9, %bb25 ], [ %phi9, %bb26 ], [ 0, %bb27 ], [ %phi9, %bb28 ], [ %phi9, %bb29 ], [ %phi, %bb30 ] + %phi10 = phi i64 [ 0, %bb ], [ 0, %bb31 ], [ %phi10, %bb32 ], [ %phi10, %bb33 ], [ %phi10, %bb36 ], [ 0, %bb39 ], [ %phi10, %bb40 ], [ %phi10, %bb41 ], [ %phi10, %bb42 ], [ 0, %bb43 ], [ %phi10, %bb45 ], [ %phi10, %bb21 ], [ %phi10, %bb22 ], [ %phi10, %bb23 ], [ 0, %bb24 ], [ %phi10, %bb25 ], [ %phi10, %bb26 ], [ %phi10, %bb27 ], [ %phi10, %bb28 ], [ %phi2, %bb29 ], [ %phi10, %bb30 ] + %phi11 = phi i64 [ undef, %bb ], [ %phi11, %bb31 ], [ %phi11, %bb32 ], [ %phi11, %bb33 ], [ %phi11, %bb36 ], [ %phi11, %bb39 ], [ %phi11, %bb40 ], [ %phi11, %bb41 ], [ 0, %bb42 ], [ 0, %bb43 ], [ %phi11, %bb45 ], [ %phi11, %bb21 ], [ %phi11, %bb22 ], [ %phi11, %bb23 ], [ %phi11, %bb24 ], [ %phi11, %bb25 ], [ %phi11, %bb26 ], [ 0, %bb27 ], [ %phi3, %bb28 ], [ %phi11, %bb29 ], [ %phi11, %bb30 ] + %phi12 = phi i64 [ 0, %bb ], [ %phi12, %bb31 ], [ 0, %bb32 ], [ %phi12, %bb33 ], [ %load37, %bb36 ], [ %phi12, %bb39 ], [ %phi12, %bb40 ], [ %phi12, %bb41 ], [ %phi12, %bb42 ], [ %phi12, %bb43 ], [ %phi12, %bb45 ], [ %phi12, %bb21 ], [ %phi12, %bb22 ], [ %phi12, %bb23 ], [ 1, %bb24 ], [ %phi12, %bb25 ], [ 0, %bb26 ], [ %phi12, %bb27 ], [ %phi12, %bb28 ], [ %phi12, %bb29 ], [ %phi12, %bb30 ] + %phi13 = phi i64 [ 0, %bb ], [ %phi13, %bb31 ], [ %phi13, %bb32 ], [ %load35, %bb33 ], [ %phi13, %bb36 ], [ %phi13, %bb39 ], [ %phi13, %bb40 ], [ %phi13, %bb41 ], [ 0, %bb42 ], [ %phi13, %bb43 ], [ %phi13, %bb45 ], [ %phi13, %bb21 ], [ %phi13, %bb22 ], [ 0, %bb23 ], [ 1, %bb24 ], [ %phi13, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ %phi13, %bb28 ], [ %phi13, %bb29 ], [ %phi13, %bb30 ] + %phi14 = phi i64 [ 0, %bb ], [ 0, %bb31 ], [ %phi14, %bb32 ], [ %load34, %bb33 ], [ 0, %bb36 ], [ %phi14, %bb39 ], [ %phi14, %bb40 ], [ %phi14, %bb41 ], [ %phi14, %bb42 ], [ %phi14, %bb43 ], [ %phi14, %bb45 ], [ %phi14, %bb21 ], [ %phi14, %bb22 ], [ 0, %bb23 ], [ %phi14, %bb24 ], [ %phi14, %bb25 ], [ %phi14, %bb26 ], [ %phi14, %bb27 ], [ %phi14, %bb28 ], [ %phi14, %bb29 ], [ %phi14, %bb30 ] + %phi15 = phi i64 [ 0, %bb ], [ %load, %bb31 ], [ %phi15, %bb32 ], [ %phi15, %bb33 ], [ %phi15, %bb36 ], [ 0, %bb39 ], [ %phi15, %bb40 ], [ %phi15, %bb41 ], [ 0, %bb42 ], [ %phi15, %bb43 ], [ %phi15, %bb45 ], [ %phi8, %bb21 ], [ %phi15, %bb22 ], [ %phi15, %bb23 ], [ %phi15, %bb24 ], [ %phi15, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ %phi15, %bb28 ], [ %phi15, %bb29 ], [ %phi15, %bb30 ] + %phi16 = phi i8 [ 3, %bb ], [ 0, %bb31 ], [ 0, %bb32 ], [ 0, %bb33 ], [ 0, %bb36 ], [ 0, %bb39 ], [ 0, %bb40 ], [ 0, %bb41 ], [ 0, %bb42 ], [ 0, %bb43 ], [ 0, %bb45 ], [ 0, %bb21 ], [ 0, %bb22 ], [ 0, %bb23 ], [ 0, %bb24 ], [ 0, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ 0, %bb28 ], [ 0, %bb29 ], [ 0, %bb30 ] + %phi17 = phi i64 [ 0, %bb ], [ %phi17, %bb31 ], [ %phi17, %bb32 ], [ %phi17, %bb33 ], [ %phi17, %bb36 ], [ 0, %bb39 ], [ %phi17, %bb40 ], [ %phi4, %bb41 ], [ %phi17, %bb42 ], [ 0, %bb43 ], [ %phi17, %bb45 ], [ %phi17, %bb21 ], [ %phi17, %bb22 ], [ %phi17, %bb23 ], [ 0, %bb24 ], [ %phi17, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ %phi17, %bb28 ], [ %phi17, %bb29 ], [ %phi17, %bb30 ] + %phi18 = phi i8 [ 0, %bb ], [ 0, %bb31 ], [ 0, %bb32 ], [ 0, %bb33 ], [ 0, %bb36 ], [ 0, %bb39 ], [ 0, %bb40 ], [ 0, %bb41 ], [ 0, %bb42 ], [ 0, %bb43 ], [ 0, %bb45 ], [ 0, %bb21 ], [ 0, %bb22 ], [ 0, %bb23 ], [ 0, %bb24 ], [ 0, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ 0, %bb28 ], [ 0, %bb29 ], [ 0, %bb30 ] + %phi19 = phi i64 [ 0, %bb ], [ %phi19, %bb31 ], [ %phi19, %bb32 ], [ %phi19, %bb33 ], [ %phi19, %bb36 ], [ 0, %bb39 ], [ %phi19, %bb40 ], [ %phi19, %bb41 ], [ %phi19, %bb42 ], [ 0, %bb43 ], [ %phi19, %bb45 ], [ %phi19, %bb21 ], [ %phi19, %bb22 ], [ %phi19, %bb23 ], [ %phi19, %bb24 ], [ %phi5, %bb25 ], [ 0, %bb26 ], [ 0, %bb27 ], [ %phi19, %bb28 ], [ %phi19, %bb29 ], [ %phi19, %bb30 ] + %phi20 = phi i64 [ 0, %bb ], [ %phi20, %bb31 ], [ %ptrtoint, %bb32 ], [ %phi20, %bb33 ], [ %phi20, %bb36 ], [ %phi20, %bb39 ], [ 0, %bb40 ], [ %phi20, %bb41 ], [ 0, %bb42 ], [ %phi20, %bb43 ], [ %phi20, %bb45 ], [ %phi20, %bb21 ], [ %phi7, %bb22 ], [ %phi20, %bb23 ], [ %phi20, %bb24 ], [ %phi20, %bb25 ], [ 0, %bb26 ], [ %phi20, %bb27 ], [ %phi20, %bb28 ], [ %phi20, %bb29 ], [ %phi20, %bb30 ] + switch i8 0, label %bb30 [ + i8 9, label %bb26 + i8 0, label %bb29 + i8 13, label %bb28 + i8 1, label %bb21 + i8 3, label %bb22 + i8 12, label %bb27 + i8 5, label %bb23 + i8 6, label %bb24 + i8 7, label %bb25 + ] + +bb21: + br i1 false, label %bb1, label %bb31 + +bb22: + br i1 false, label %bb1, label %bb32 + +bb23: + br i1 false, label %bb1, label %bb33 + +bb24: + br i1 false, label %bb1, label %bb36 + +bb25: + br i1 false, label %bb1, label %bb39 + +bb26: + br i1 false, label %bb40, label %bb1 + +bb27: + br i1 false, label %bb41, label %bb1 + +bb28: + br i1 false, label %bb1, label %bb42 + +bb29: + br i1 false, label %bb1, label %bb43 + +bb30: + br i1 false, label %bb1, label %bb45 + +bb31: + %load = load i64, ptr null, align 8 + br label %bb1 + +bb32: + %ptrtoint = ptrtoint ptr null to i64 + br label %bb1 + +bb33: + %load34 = load i64, ptr null, align 8 + %load35 = load i64, ptr null, align 8 + br label %bb1 + +bb36: + %load37 = load i64, ptr null, align 8 + %load38 = load i64, ptr null, align 8 + br label %bb1 + +bb39: + br label %bb1 + +bb40: + br label %bb1 + +bb41: + br label %bb1 + +bb42: + br label %bb1 + +bb43: + %load44 = load i64, ptr null, align 8 + br label %bb1 + +bb45: + %load46 = load i64, ptr null, align 8 + br label %bb1 +} + diff --git a/llvm/test/Transforms/SLPVectorizer/alternate-opcode-sindle-bv.ll b/llvm/test/Transforms/SLPVectorizer/alternate-opcode-sindle-bv.ll index 9b6511d0d8284..d880c6b1783c8 100644 --- a/llvm/test/Transforms/SLPVectorizer/alternate-opcode-sindle-bv.ll +++ b/llvm/test/Transforms/SLPVectorizer/alternate-opcode-sindle-bv.ll @@ -17,12 +17,12 @@ define <2 x i32> @test(i32 %arg) { ; AARCH64-LABEL: define <2 x i32> @test( ; AARCH64-SAME: i32 [[ARG:%.*]]) { ; AARCH64-NEXT: bb: -; AARCH64-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 -; AARCH64-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[TMP0]], zeroinitializer -; AARCH64-NEXT: [[TMP2:%.*]] = extractelement <2 x i32> [[TMP1]], i32 0 -; AARCH64-NEXT: [[TMP3:%.*]] = extractelement <2 x i32> [[TMP1]], i32 1 +; AARCH64-NEXT: [[TMP2:%.*]] = or i32 [[ARG]], 0 +; AARCH64-NEXT: [[TMP3:%.*]] = mul i32 0, 1 ; AARCH64-NEXT: [[MUL1:%.*]] = mul i32 [[TMP2]], [[TMP3]] ; AARCH64-NEXT: [[CMP:%.*]] = icmp ugt i32 0, [[MUL1]] +; AARCH64-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> poison, i32 [[TMP2]], i32 0 +; AARCH64-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> [[TMP0]], i32 [[TMP3]], i32 1 ; AARCH64-NEXT: ret <2 x i32> [[TMP1]] ; bb: diff --git a/llvm/test/Transforms/SROA/invariant-group.ll b/llvm/test/Transforms/SROA/invariant-group.ll index 1be6f6e2fc32b..c9c9e031ca95f 100644 --- a/llvm/test/Transforms/SROA/invariant-group.ll +++ b/llvm/test/Transforms/SROA/invariant-group.ll @@ -11,10 +11,17 @@ declare i32 @somevalue() define void @f() { ; CHECK-LABEL: @f( +; CHECK-NEXT: [[A:%.*]] = alloca [[T:%.*]], align 8 +; CHECK-NEXT: [[A1_I8_INV:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[A]]) +; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1 ; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue() ; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue() -; CHECK-NEXT: call void @h(i32 [[SV1]]) -; CHECK-NEXT: call void @h(i32 [[SV2]]) +; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]] +; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4 +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]] +; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4 +; CHECK-NEXT: call void @h(i32 [[V1]]) +; CHECK-NEXT: call void @h(i32 [[V2]]) ; CHECK-NEXT: ret void ; %a = alloca %t @@ -44,7 +51,7 @@ define void @g() { ; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i32 0, i32 1 ; CHECK-NEXT: [[SV1:%.*]] = call i32 @somevalue() ; CHECK-NEXT: [[SV2:%.*]] = call i32 @somevalue() -; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0:![0-9]+]] +; CHECK-NEXT: store i32 [[SV1]], ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]] ; CHECK-NEXT: store i32 [[SV2]], ptr [[A2]], align 4 ; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[A1_I8_INV]], align 4, !invariant.group [[META0]] ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[A2]], align 4 @@ -81,6 +88,9 @@ define void @g() { define void @store_and_launder() { ; CHECK-LABEL: @store_and_launder( +; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr [[VALPTR]], align 4 +; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]]) ; CHECK-NEXT: ret void ; %valptr = alloca i32, align 4 @@ -91,7 +101,10 @@ define void @store_and_launder() { define i32 @launder_and_load() { ; CHECK-LABEL: @launder_and_load( -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]]) +; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[VALPTR]], align 4 +; CHECK-NEXT: ret i32 [[V2]] ; %valptr = alloca i32, align 4 %barr = call ptr @llvm.launder.invariant.group.p0(ptr %valptr) @@ -101,6 +114,9 @@ define i32 @launder_and_load() { define void @launder_and_ptr_arith() { ; CHECK-LABEL: @launder_and_ptr_arith( +; CHECK-NEXT: [[VALPTR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[VALPTR]]) +; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i32, ptr [[VALPTR]], i32 0 ; CHECK-NEXT: ret void ; %valptr = alloca i32, align 4 @@ -140,9 +156,13 @@ end: define void @partial_promotion_of_alloca() { ; CHECK-LABEL: @partial_promotion_of_alloca( -; CHECK-NEXT: [[STRUCT_PTR_SROA_2:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store volatile i32 0, ptr [[STRUCT_PTR_SROA_2]], align 4 -; CHECK-NEXT: [[STRUCT_PTR_SROA_2_0_STRUCT_PTR_SROA_2_4_LOAD_VAL:%.*]] = load volatile i32, ptr [[STRUCT_PTR_SROA_2]], align 4 +; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], align 4 +; CHECK-NEXT: [[FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 0 +; CHECK-NEXT: store i32 0, ptr [[FIELD_PTR]], align 4 +; CHECK-NEXT: [[VOLATILE_FIELD_PTR:%.*]] = getelementptr inbounds [[T]], ptr [[STRUCT_PTR]], i32 0, i32 1 +; CHECK-NEXT: store volatile i32 0, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]] +; CHECK-NEXT: [[BARR:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]]) +; CHECK-NEXT: [[LOAD_VAL:%.*]] = load volatile i32, ptr [[VOLATILE_FIELD_PTR]], align 4, !invariant.group [[META0]] ; CHECK-NEXT: ret void ; %struct_ptr = alloca %t, align 4 @@ -155,6 +175,61 @@ define void @partial_promotion_of_alloca() { ret void } +define void @memcpy_after_laundering_alloca(ptr %ptr) { +; CHECK-LABEL: @memcpy_after_laundering_alloca( +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca { i64, i64 }, align 8 +; CHECK-NEXT: [[LAUNDER:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[ALLOCA]]) +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[LAUNDER]], ptr [[PTR:%.*]], i64 16, i1 false) +; CHECK-NEXT: ret void +; + %alloca = alloca { i64, i64 }, align 8 + %launder = call ptr @llvm.launder.invariant.group.p0(ptr %alloca) + call void @llvm.memcpy.p0.p0.i64(ptr %launder, ptr %ptr, i64 16, i1 false) + ret void +} + +define void @memcpy_after_laundering_alloca_slices(ptr %ptr) { +; CHECK-LABEL: @memcpy_after_laundering_alloca_slices( +; CHECK-NEXT: [[ALLOCA:%.*]] = alloca { [16 x i8], i64, [16 x i8] }, align 8 +; CHECK-NEXT: [[LAUNDER:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[ALLOCA]]) +; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[LAUNDER]], i64 16 +; CHECK-NEXT: store i64 0, ptr [[GEP]], align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[LAUNDER]], ptr [[PTR:%.*]], i64 40, i1 false) +; CHECK-NEXT: ret void +; + %alloca = alloca { [16 x i8], i64, [16 x i8] }, align 8 + %launder = call ptr @llvm.launder.invariant.group.p0(ptr %alloca) + %gep = getelementptr i8, ptr %launder, i64 16 + store i64 0, ptr %gep + call void @llvm.memcpy.p0.p0.i64(ptr %launder, ptr %ptr, i64 40, i1 false) + ret void +} + +define void @test_agg_store() { +; CHECK-LABEL: @test_agg_store( +; CHECK-NEXT: [[STRUCT_PTR:%.*]] = alloca [[T:%.*]], i64 1, align 4 +; CHECK-NEXT: [[STRUCT_PTR_FRESH:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[STRUCT_PTR]]) +; CHECK-NEXT: [[STRUCT:%.*]] = call [[T]] @[[MAKE_T:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]]() +; CHECK-NEXT: store [[T]] [[STRUCT]], ptr [[STRUCT_PTR_FRESH]], align 4, !invariant.group [[META0]] +; CHECK-NEXT: [[FIRST_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 0 +; CHECK-NEXT: [[FIRST:%.*]] = load i32, ptr [[FIRST_PTR]], align 4 +; CHECK-NEXT: [[SECOND_PTR:%.*]] = getelementptr [[T]], ptr [[STRUCT_PTR_FRESH]], i32 0, i32 1 +; CHECK-NEXT: [[SECOND:%.*]] = load i32, ptr [[SECOND_PTR]], align 4 +; CHECK-NEXT: ret void +; + %struct_ptr = alloca %t, i64 1, align 4 + %struct_ptr_fresh = call ptr @llvm.launder.invariant.group.p0(ptr %struct_ptr) + %struct = call %t @make_t() + store %t %struct, ptr %struct_ptr_fresh, align 4, !invariant.group !0 + %first_ptr = getelementptr %t, ptr %struct_ptr_fresh, i32 0, i32 0 + %first = load i32, ptr %first_ptr, align 4 + %second_ptr = getelementptr %t, ptr %struct_ptr_fresh, i32 0, i32 1 + %second = load i32, ptr %second_ptr, align 4 + ret void +} + +declare %t @make_t() + declare void @use(ptr) !0 = !{} diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll new file mode 100644 index 0000000000000..b927af6b92f7c --- /dev/null +++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll @@ -0,0 +1,19 @@ +; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s +; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s +; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s + +; Check that __cfi_check is emitted on the full LTO side with +; attributes preserved. + +; M0: define void @f() +define void @f() !type !{!"f1", i32 0} { + ret void +} + +; M1: define void @__cfi_check() #0 +define void @__cfi_check() #0 { + ret void +} + +; M1: attributes #0 = { "branch-target-enforcement" } +attributes #0 = { "branch-target-enforcement" } diff --git a/llvm/test/Transforms/VectorCombine/AArch64/load-extractelement-scalarization.ll b/llvm/test/Transforms/VectorCombine/AArch64/load-extractelement-scalarization.ll index e6e5f5196d3da..5c035d29a7ea2 100644 --- a/llvm/test/Transforms/VectorCombine/AArch64/load-extractelement-scalarization.ll +++ b/llvm/test/Transforms/VectorCombine/AArch64/load-extractelement-scalarization.ll @@ -669,10 +669,10 @@ define i1 @load_with_non_power_of_2_element_type_2(ptr %x) { ; Scalarizing the load for multiple constant indices may not be profitable. define i32 @load_multiple_extracts_with_constant_idx(ptr %x) { ; CHECK-LABEL: @load_multiple_extracts_with_constant_idx( -; CHECK-NEXT: [[LV:%.*]] = load <4 x i32>, ptr [[X:%.*]], align 16 -; CHECK-NEXT: [[SHIFT:%.*]] = shufflevector <4 x i32> [[LV]], <4 x i32> poison, <4 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[LV]], [[SHIFT]] -; CHECK-NEXT: [[RES:%.*]] = extractelement <4 x i32> [[TMP1]], i32 0 +; CHECK-NEXT: [[E_0:%.*]] = load i32, ptr [[TMP1:%.*]], align 16 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <4 x i32>, ptr [[TMP1]], i32 0, i32 1 +; CHECK-NEXT: [[E_1:%.*]] = load i32, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[RES:%.*]] = add i32 [[E_0]], [[E_1]] ; CHECK-NEXT: ret i32 [[RES]] ; %lv = load <4 x i32>, ptr %x @@ -686,10 +686,10 @@ define i32 @load_multiple_extracts_with_constant_idx(ptr %x) { ; because the vector large vector requires 2 vector registers. define i32 @load_multiple_extracts_with_constant_idx_profitable(ptr %x) { ; CHECK-LABEL: @load_multiple_extracts_with_constant_idx_profitable( -; CHECK-NEXT: [[LV:%.*]] = load <8 x i32>, ptr [[X:%.*]], align 16 -; CHECK-NEXT: [[SHIFT:%.*]] = shufflevector <8 x i32> [[LV]], <8 x i32> poison, <8 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = add <8 x i32> [[LV]], [[SHIFT]] -; CHECK-NEXT: [[RES:%.*]] = extractelement <8 x i32> [[TMP1]], i32 0 +; CHECK-NEXT: [[E_0:%.*]] = load i32, ptr [[TMP1:%.*]], align 16 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds <8 x i32>, ptr [[TMP1]], i32 0, i32 6 +; CHECK-NEXT: [[E_1:%.*]] = load i32, ptr [[TMP2]], align 8 +; CHECK-NEXT: [[RES:%.*]] = add i32 [[E_0]], [[E_1]] ; CHECK-NEXT: ret i32 [[RES]] ; %lv = load <8 x i32>, ptr %x, align 16 diff --git a/llvm/test/Transforms/VectorCombine/AArch64/scalarize-ext-extract-endian.ll b/llvm/test/Transforms/VectorCombine/AArch64/scalarize-ext-extract-endian.ll new file mode 100644 index 0000000000000..9796faf2e6feb --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/AArch64/scalarize-ext-extract-endian.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes='vector-combine' -S -mtriple=aarch64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=LE +; RUN: opt -passes='vector-combine' -S -mtriple=aarch64_be-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=BE + +define i64 @g(<8 x i8> %v) { +; LE-LABEL: @g( +; LE-NEXT: [[TMP1:%.*]] = freeze <8 x i8> [[V:%.*]] +; LE-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to i64 +; LE-NEXT: [[TMP3:%.*]] = lshr i64 [[TMP2]], 56 +; LE-NEXT: [[TMP4:%.*]] = and i64 [[TMP2]], 255 +; LE-NEXT: [[Z:%.*]] = zext <8 x i8> [[V]] to <8 x i64> +; LE-NEXT: [[E0:%.*]] = extractelement <8 x i64> [[Z]], i32 0 +; LE-NEXT: [[E7:%.*]] = extractelement <8 x i64> [[Z]], i32 7 +; LE-NEXT: [[SUM:%.*]] = add i64 [[TMP4]], [[TMP3]] +; LE-NEXT: ret i64 [[SUM]] +; +; BE-LABEL: @g( +; BE-NEXT: [[TMP1:%.*]] = freeze <8 x i8> [[V:%.*]] +; BE-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to i64 +; BE-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 255 +; BE-NEXT: [[TMP4:%.*]] = lshr i64 [[TMP2]], 56 +; BE-NEXT: [[Z:%.*]] = zext <8 x i8> [[V]] to <8 x i64> +; BE-NEXT: [[E0:%.*]] = extractelement <8 x i64> [[Z]], i32 0 +; BE-NEXT: [[E7:%.*]] = extractelement <8 x i64> [[Z]], i32 7 +; BE-NEXT: [[SUM:%.*]] = add i64 [[TMP4]], [[TMP3]] +; BE-NEXT: ret i64 [[SUM]] +; + %z = zext <8 x i8> %v to <8 x i64> + %e0 = extractelement <8 x i64> %z, i32 0 + %e7 = extractelement <8 x i64> %z, i32 7 + %sum = add i64 %e0, %e7 + ret i64 %sum +} + + + diff --git a/llvm/test/Transforms/VectorCombine/PowerPC/lit.local.cfg b/llvm/test/Transforms/VectorCombine/PowerPC/lit.local.cfg new file mode 100644 index 0000000000000..15af315f104fc --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if 'PowerPC' not in config.root.targets: + config.unsupported = True diff --git a/llvm/test/Transforms/VectorCombine/PowerPC/scalarize-ext-extract.ll b/llvm/test/Transforms/VectorCombine/PowerPC/scalarize-ext-extract.ll new file mode 100644 index 0000000000000..a9b719920c341 --- /dev/null +++ b/llvm/test/Transforms/VectorCombine/PowerPC/scalarize-ext-extract.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes='vector-combine' -S -mtriple=powerpc64-ibm-aix-xcoff %s -o - | FileCheck %s --check-prefix=BE + +define i64 @g(<8 x i8> %v) { +; BE-LABEL: @g( +; BE-NEXT: [[TMP1:%.*]] = freeze <8 x i8> [[V:%.*]] +; BE-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to i64 +; BE-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 255 +; BE-NEXT: [[TMP4:%.*]] = lshr i64 [[TMP2]], 56 +; BE-NEXT: [[Z:%.*]] = zext <8 x i8> [[V]] to <8 x i64> +; BE-NEXT: [[E0:%.*]] = extractelement <8 x i64> [[Z]], i32 0 +; BE-NEXT: [[E7:%.*]] = extractelement <8 x i64> [[Z]], i32 7 +; BE-NEXT: [[SUM:%.*]] = add i64 [[TMP4]], [[TMP3]] +; BE-NEXT: ret i64 [[SUM]] +; + %z = zext <8 x i8> %v to <8 x i64> + %e0 = extractelement <8 x i64> %z, i32 0 + %e7 = extractelement <8 x i64> %z, i32 7 + %sum = add i64 %e0, %e7 + ret i64 %sum +} + diff --git a/llvm/test/Transforms/VectorCombine/X86/intrinsic-scalarize.ll b/llvm/test/Transforms/VectorCombine/X86/intrinsic-scalarize.ll index 5f3229398792a..ad5f5a7107c2b 100644 --- a/llvm/test/Transforms/VectorCombine/X86/intrinsic-scalarize.ll +++ b/llvm/test/Transforms/VectorCombine/X86/intrinsic-scalarize.ll @@ -13,8 +13,7 @@ define <2 x float> @maxnum(float %x, float %y) { ; AVX2-LABEL: define <2 x float> @maxnum( ; AVX2-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0:[0-9]+]] { ; AVX2-NEXT: [[V_SCALAR:%.*]] = call float @llvm.maxnum.f32(float [[X]], float [[Y]]) -; AVX2-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> poison, <2 x float> poison) -; AVX2-NEXT: [[V:%.*]] = insertelement <2 x float> [[TMP1]], float [[V_SCALAR]], i64 0 +; AVX2-NEXT: [[V:%.*]] = insertelement <2 x float> poison, float [[V_SCALAR]], i64 0 ; AVX2-NEXT: ret <2 x float> [[V]] ; %x.insert = insertelement <2 x float> poison, float %x, i32 0 diff --git a/llvm/test/Transforms/VectorCombine/binop-scalarize.ll b/llvm/test/Transforms/VectorCombine/binop-scalarize.ll index 52a706a0b59a7..bc07f8b086496 100644 --- a/llvm/test/Transforms/VectorCombine/binop-scalarize.ll +++ b/llvm/test/Transforms/VectorCombine/binop-scalarize.ll @@ -20,3 +20,22 @@ define <4 x i8> @udiv_ub(i8 %x, i8 %y) { %v = udiv <4 x i8> %x.insert, %y.insert ret <4 x i8> %v } + + +; Unfoldable constant expression may cause infinite loop between +; scalarizing insertelement and folding binop(insert(x,a,idx),insert(y,b,idx)) +@val = external hidden global ptr, align 8 + +define <2 x i64> @pr153012(i64 %idx) #0 { +; CHECK-LABEL: define <2 x i64> @pr153012( +; CHECK-SAME: i64 [[IDX:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[A:%.*]] = insertelement <2 x i64> , i64 [[IDX]], i32 0 +; CHECK-NEXT: [[B:%.*]] = or disjoint <2 x i64> splat (i64 2), [[A]] +; CHECK-NEXT: ret <2 x i64> [[B]] +; +entry: + %a = insertelement <2 x i64> , i64 %idx, i32 0 + %b = or disjoint <2 x i64> splat (i64 2), %a + ret <2 x i64> %b +} diff --git a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll index 9e43a28bf1e59..abd98a4dc64b8 100644 --- a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll +++ b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll @@ -5,8 +5,7 @@ define <4 x i32> @umax_fixed(i32 %x, i32 %y) { ; CHECK-LABEL: define <4 x i32> @umax_fixed( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]]) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.umax.v4i32(<4 x i32> poison, <4 x i32> poison) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x i32> [[V]] ; %x.insert = insertelement <4 x i32> poison, i32 %x, i32 0 @@ -19,8 +18,7 @@ define @umax_scalable(i32 %x, i32 %y) { ; CHECK-LABEL: define @umax_scalable( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]]) -; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.umax.nxv4i32( poison, poison) -; CHECK-NEXT: [[V:%.*]] = insertelement [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret [[V]] ; %x.insert = insertelement poison, i32 %x, i32 0 @@ -33,8 +31,7 @@ define <4 x i32> @umax_fixed_lhs_const(i32 %x) { ; CHECK-LABEL: define <4 x i32> @umax_fixed_lhs_const( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 1, i32 [[X]]) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.umax.v4i32(<4 x i32> , <4 x i32> poison) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x i32> [[V]] ; %x.insert = insertelement <4 x i32> poison, i32 %x, i32 0 @@ -46,8 +43,7 @@ define <4 x i32> @umax_fixed_rhs_const(i32 %x) { ; CHECK-LABEL: define <4 x i32> @umax_fixed_rhs_const( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.umax.v4i32(<4 x i32> poison, <4 x i32> ) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x i32> poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x i32> [[V]] ; %x.insert = insertelement <4 x i32> poison, i32 %x, i32 0 @@ -59,8 +55,7 @@ define @umax_scalable_lhs_const(i32 %x) { ; CHECK-LABEL: define @umax_scalable_lhs_const( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 42, i32 [[X]]) -; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.umax.nxv4i32( splat (i32 42), poison) -; CHECK-NEXT: [[V:%.*]] = insertelement [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret [[V]] ; %x.insert = insertelement poison, i32 %x, i32 0 @@ -72,8 +67,7 @@ define @umax_scalable_rhs_const(i32 %x) { ; CHECK-LABEL: define @umax_scalable_rhs_const( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 42) -; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.umax.nxv4i32( poison, splat (i32 42)) -; CHECK-NEXT: [[V:%.*]] = insertelement [[TMP1]], i32 [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement poison, i32 [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret [[V]] ; %x.insert = insertelement poison, i32 %x, i32 0 @@ -100,8 +94,7 @@ define <4 x float> @fabs_fixed(float %x) { ; CHECK-LABEL: define <4 x float> @fabs_fixed( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> poison) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> [[TMP1]], float [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> poison, float [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x float> [[V]] ; %x.insert = insertelement <4 x float> poison, float %x, i32 0 @@ -113,8 +106,7 @@ define @fabs_scalable(float %x) { ; CHECK-LABEL: define @fabs_scalable( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.fabs.nxv4f32( poison) -; CHECK-NEXT: [[V:%.*]] = insertelement [[TMP1]], float [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement poison, float [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret [[V]] ; %x.insert = insertelement poison, float %x, i32 0 @@ -126,8 +118,7 @@ define <4 x float> @fma_fixed(float %x, float %y, float %z) { ; CHECK-LABEL: define <4 x float> @fma_fixed( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call float @llvm.fma.f32(float [[X]], float [[Y]], float [[Z]]) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> poison, <4 x float> poison, <4 x float> poison) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> [[TMP1]], float [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> poison, float [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x float> [[V]] ; %x.insert = insertelement <4 x float> poison, float %x, i32 0 @@ -141,8 +132,7 @@ define @fma_scalable(float %x, float %y, float %z) { ; CHECK-LABEL: define @fma_scalable( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call float @llvm.fma.f32(float [[X]], float [[Y]], float [[Z]]) -; CHECK-NEXT: [[TMP1:%.*]] = call @llvm.fma.nxv4f32( poison, poison, poison) -; CHECK-NEXT: [[V:%.*]] = insertelement [[TMP1]], float [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement poison, float [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret [[V]] ; %x.insert = insertelement poison, float %x, i32 0 @@ -156,8 +146,7 @@ define <4 x float> @scalar_argument(float %x) { ; CHECK-LABEL: define <4 x float> @scalar_argument( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[V_SCALAR:%.*]] = call float @llvm.powi.f32.i32(float [[X]], i32 42) -; CHECK-NEXT: [[TMP1:%.*]] = call <4 x float> @llvm.powi.v4f32.i32(<4 x float> poison, i32 42) -; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> [[TMP1]], float [[V_SCALAR]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> poison, float [[V_SCALAR]], i64 0 ; CHECK-NEXT: ret <4 x float> [[V]] ; %x.insert = insertelement <4 x float> poison, float %x, i32 0 diff --git a/llvm/test/tools/llvm-objcopy/COFF/exe-bogus-assoc.test b/llvm/test/tools/llvm-objcopy/COFF/exe-bogus-assoc.test new file mode 100644 index 0000000000000..12f14b5d58e1c --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/COFF/exe-bogus-assoc.test @@ -0,0 +1,134 @@ +## Test that bogus associative section symbols in executables are ignored. +## +## The executable contains two (bogus) associative section symbols, both for +## (parts of) the .rdata section; one pointing at the .debug_info section +## (which will be stripped out) and one pointing at a nonexistent section. +## +## Check that stripping does succeed, and that it doesn't end up removing +## the .rdata section. + +# RUN: yaml2obj %s -o %t.in.exe + +# RUN: llvm-strip --strip-debug %t.in.exe -o %t.out.exe +# RUN: llvm-readobj --sections %t.out.exe | FileCheck %s + +# CHECK: Name: .rdata + +--- !COFF +OptionalHeader: + AddressOfEntryPoint: 4096 + ImageBase: 5368709120 + SectionAlignment: 4096 + FileAlignment: 512 + MajorOperatingSystemVersion: 4 + MinorOperatingSystemVersion: 0 + MajorImageVersion: 0 + MinorImageVersion: 0 + MajorSubsystemVersion: 5 + MinorSubsystemVersion: 2 + Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI + DLLCharacteristics: [ ] + SizeOfStackReserve: 2097152 + SizeOfStackCommit: 4096 + SizeOfHeapReserve: 1048576 + SizeOfHeapCommit: 4096 +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 4096 + VirtualSize: 48 + SectionData: E806000000E802000000C3C3C30F1F00FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000 + SizeOfRawData: 512 + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 8192 + VirtualSize: 4 + SectionData: '00000000' + SizeOfRawData: 512 + - Name: .debug_info + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 16384 + VirtualSize: 4 + SectionData: '00000000' + SizeOfRawData: 512 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 11 + NumberOfRelocations: 2 + NumberOfLinenumbers: 0 + CheckSum: 1703692295 + Number: 1 + - Name: '.text$func1' + Value: 11 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 40735498 + Number: 3 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: .rdata + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 3 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '.text$func2' + Value: 12 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 40735498 + Number: 4 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: .rdata + Value: 1 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 4 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: .debug_info + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 +... diff --git a/llvm/test/tools/llvm-objcopy/COFF/strip-invalid-symidx-section.test b/llvm/test/tools/llvm-objcopy/COFF/strip-invalid-symidx-section.test new file mode 100644 index 0000000000000..2b01116800091 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/COFF/strip-invalid-symidx-section.test @@ -0,0 +1,188 @@ +## Test that we bail out if a section consisting of symidx is invalid. + +## In this case, the symbol .gfids$y is not present at all. +# RUN: yaml2obj %s --docnum=1 -o %t1.in.o +# RUN: not llvm-objcopy --strip-debug %t1.in.o %t1.out.o 2>&1 | FileCheck %s --check-prefix=ERROR-NOSYM -DFILE=%t1.out.o + +# ERROR-NOSYM: error: '[[FILE]]': section '.gfids$y' does not have the corresponding symbol or the symbol has unexpected format + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + - Name: '.gfids$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '04000000' + SizeOfRawData: 8 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + +## In this case, the symbol .giats$y has a non-zero offset. +# RUN: yaml2obj %s --docnum=2 -o %t2.in.o +# RUN: not llvm-objcopy --strip-debug %t2.in.o %t2.out.o 2>&1 | FileCheck %s --check-prefix=ERROR-OFFSET -DFILE=%t2.out.o + +# ERROR-OFFSET: error: '[[FILE]]': section '.giats$y' does not have the corresponding symbol or the symbol has unexpected format + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + - Name: '.giats$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0600000010000000' + SizeOfRawData: 8 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: '.giats$y' + Value: 42 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1167279533 + Number: 5 + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + +## In this case, the symbol .gljmp$y has a non-static storage class. +# RUN: yaml2obj %s --docnum=3 -o %t3.in.o +# RUN: not llvm-objcopy --strip-debug %t3.in.o %t3.out.o 2>&1 | FileCheck %s --check-prefix=ERROR-EXTERNAL -DFILE=%t3.out.o + +# ERROR-EXTERNAL: error: '[[FILE]]': section '.gljmp$y' does not have the corresponding symbol or the symbol has unexpected format + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + - Name: '.gljmp$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0600000010000000' + SizeOfRawData: 8 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: '.gljmp$y' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + +## In this case, .gfids$y contains a symbol index that is not present in the +## symbol table. Generally the behavior should be the same for every section consisting +## of .symidx directives, e.g .giats$y, .gljmp$y and .gehcont$y. +# RUN: yaml2obj %s --docnum=4 -o %t4.in.o +# RUN: not llvm-objcopy --strip-debug %t4.in.o %t4.out.o 2>&1 | FileCheck %s --check-prefix=ERROR-SYMIDX -DFILE=%t4.out.o + +# ERROR-SYMIDX: error: '[[FILE]]': section '.gfids$y' contains a .symidx (16) that is incorrect or was stripped +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + - Name: '.gfids$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0400000010000000' + SizeOfRawData: 8 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: '.gfids$y' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 1167279533 + Number: 5 + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-objcopy/COFF/strip-update-symidx-section.test b/llvm/test/tools/llvm-objcopy/COFF/strip-update-symidx-section.test new file mode 100644 index 0000000000000..04ec26afb644d --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/COFF/strip-update-symidx-section.test @@ -0,0 +1,173 @@ +## Check sections consisting only of .symidx directives. The test checks that +## indices in the sections are updated after stripping as the symbol table could +## be changed during stripping. +# RUN: yaml2obj %s -o %t.in.o + +# RUN: llvm-objcopy --strip-debug %t.in.o %t.out.o +# RUN: llvm-readobj -s -x '.gehcont$y' -x '.gfids$y' -x '.giats$y' -x '.gljmp$y' %t.out.o | FileCheck %s + +# CHECK: Symbols [ +# CHECK: Name: .text +# CHECK: Name: .gehcont$y +# CHECK: AuxSectionDef { +# CHECK: Checksum: 0x82EA2D2 +# CHECK: } +# CHECK: Name: $ehgcr_0_1 +# CHECK: Name: .gfids$y +# CHECK: AuxSectionDef { +# CHECK: Checksum: 0xAF00C48B +# CHECK: } +# CHECK: Name: .giats$y +# CHECK: AuxSectionDef { +# CHECK: Checksum: 0x4AD6BFB8 +# CHECK: } +# CHECK: Name: .gljmp$y +# CHECK: AuxSectionDef { +# CHECK: Checksum: 0xD457699C +# CHECK: } +# CHECK: Name: foo +# CHECK: ] + +# CHECK: Hex dump of section '.gehcont$y': +# CHECK-NEXT: 0x00000000 04000000 04000000 04000000 + +# CHECK: Hex dump of section '.gfids$y': +# CHECK-NEXT: 0x00000000 0b000000 0d000000 + +# CHECK: Hex dump of section '.giats$y': +# CHECK-NEXT: 0x00000000 0c000000 + +# CHECK: Hex dump of section '.gljmp$y': +# CHECK-NEXT: 0x00000000 0b000000 0c000000 0d000000 + + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 04000000F100000044656275672073656374696F6E20746F20626520737472697070656400 + SizeOfRawData: 37 + - Name: '.gehcont$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '060000000600000006000000' + SizeOfRawData: 12 + - Name: '.gfids$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0d0000000f000000' + SizeOfRawData: 8 + - Name: '.giats$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0e000000' + SizeOfRawData: 4 + - Name: '.gljmp$y' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0d0000000e0000000f000000' + SizeOfRawData: 12 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + - Name: '.debug$S' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 37 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 820498156 + Number: 2 + - Name: '.gehcont$y' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0x30E7CEEC + Number: 3 + - Name: '$ehgcr_0_1' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '.gfids$y' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0x459345AD + Number: 4 + - Name: '.giats$y' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0x31852256 + Number: 5 + - Name: '.gljmp$y' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 16 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0xC608680B + Number: 6 + - Name: foo + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: baz + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-objdump/ELF/Hexagon/hexagon-bundles.s b/llvm/test/tools/llvm-objdump/ELF/Hexagon/hexagon-bundles.s new file mode 100644 index 0000000000000..6a4927e4af2a4 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/Hexagon/hexagon-bundles.s @@ -0,0 +1,47 @@ +/// Checks that various hexagon scenarios are handled correctly: +/// - branch targets +/// - endloops +/// - inline-relocs +/// - multi-insn bundles + +{ + r6 = sub(r1, r0) + r7 = and(r4, #0x0) + if (p1) jump:t target1 + if (p2) jump:nt target2 +} + +{ + r8 = r7 + r9 = add(r8, #0) + r10 = memw(r9) +} :endloop0 + +{ jump ##sym } + +target1: + nop + +target2: + nop + +// RUN: llvm-mc %s --triple=hexagon -filetype=obj | llvm-objdump -d -r - | FileCheck %s + +// CHECK: 00000000 <.text>: +// CHECK-NEXT: 0: 12 51 00 5c 5c005112 { if (p1) jump:t 0x24 +// CHECK-NEXT: 4: 14 42 00 5c 5c004214 if (p2) jump:nt 0x28 +// CHECK-NEXT: 8: 06 41 20 f3 f3204106 r6 = sub(r1,r0) +// CHECK-NEXT: c: 07 c0 04 76 7604c007 r7 = and(r4,#0x0) } +// CHECK-NEXT: 10: 08 80 67 70 70678008 { r8 = r7 +// CHECK-NEXT: 14: 09 40 08 b0 b0084009 r9 = add(r8,#0x0) +// CHECK-NEXT: 18: 0a c0 89 91 9189c00a r10 = memw(r9+#0x0) } :endloop0 +// CHECK-NEXT: 1c: 00 40 00 00 00004000 { immext(#0x0) +// CHECK-NEXT: 0000001c: R_HEX_B32_PCREL_X sym +// CHECK-NEXT: 20: 00 c0 00 58 5800c000 jump 0x1c <.text+0x1c> } +// CHECK-NEXT: 00000020: R_HEX_B22_PCREL_X sym+0x4 +// CHECK-EMPTY: +// CHECK-NEXT: 00000024 : +// CHECK-NEXT: 24: 00 c0 00 7f 7f00c000 { nop } +// CHECK-EMPTY: +// CHECK-NEXT: 00000028 : +// CHECK-NEXT: 28: 00 c0 00 7f 7f00c000 { nop } diff --git a/llvm/test/tools/llvm-objdump/ELF/Hexagon/packet-reset-on-label.s b/llvm/test/tools/llvm-objdump/ELF/Hexagon/packet-reset-on-label.s new file mode 100644 index 0000000000000..02a52bbb3fbd8 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/Hexagon/packet-reset-on-label.s @@ -0,0 +1,23 @@ +// RUN: llvm-mc -triple=hexagon -mcpu=hexagonv75 -filetype=obj %s \ +// RUN: | llvm-objdump -d - \ +// RUN: | FileCheck %s + +foo: + { nop } + /// a nop without end-of-packet bits set to simulate data that is + /// not a proper packet end. + .long 0x7f004000 +bar: + { nop + nop + } + +// CHECK-LABEL: : +// CHECK: { nop } +// CHECK-NEXT: { nop + +/// The instruction starting after should start in a new packet. +// CHECK-LABEL: : +// CHECK: { nop +// CHECK-NEXT: nop } + diff --git a/llvm/tools/llvm-mc/Disassembler.cpp b/llvm/tools/llvm-mc/Disassembler.cpp index 607184e3b7247..86727931067a5 100644 --- a/llvm/tools/llvm-mc/Disassembler.cpp +++ b/llvm/tools/llvm-mc/Disassembler.cpp @@ -45,7 +45,11 @@ static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes, MCInst Inst; MCDisassembler::DecodeStatus S; - S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls()); + if (STI.getTargetTriple().getArch() == Triple::hexagon) + S = DisAsm.getInstructionBundle(Inst, Size, Data.slice(Index), Index, + nulls()); + else + S = DisAsm.getInstruction(Inst, Size, Data.slice(Index), Index, nulls()); switch (S) { case MCDisassembler::Fail: SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]), diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index c5967cd090eec..221b884e0c06c 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -693,11 +693,41 @@ class PrettyPrinter { } else OS << "\t"; } + + virtual void emitPostInstructionInfo(formatted_raw_ostream &FOS, + const MCAsmInfo &MAI, + const MCSubtargetInfo &STI, + StringRef Comments, + LiveVariablePrinter &LVP) { + do { + if (!Comments.empty()) { + // Emit a line of comments. + StringRef Comment; + std::tie(Comment, Comments) = Comments.split('\n'); + // MAI.getCommentColumn() assumes that instructions are printed at the + // position of 8, while getInstStartColumn() returns the actual + // position. + unsigned CommentColumn = + MAI.getCommentColumn() - 8 + getInstStartColumn(STI); + FOS.PadToColumn(CommentColumn); + FOS << MAI.getCommentString() << ' ' << Comment; + } + LVP.printAfterInst(FOS); + FOS << "\n"; + } while (!Comments.empty()); + FOS.flush(); + } + + // Hook invoked when starting to disassemble a symbol at the current position. + // Default is no-op. + virtual void onSymbolStart() {} }; PrettyPrinter PrettyPrinterInst; class HexagonPrettyPrinter : public PrettyPrinter { public: + void onSymbolStart() override { reset(); } + void printLead(ArrayRef Bytes, uint64_t Address, formatted_raw_ostream &OS) { if (LeadingAddr) @@ -714,6 +744,35 @@ class HexagonPrettyPrinter : public PrettyPrinter { } } } + + std::string getInstructionSeparator() const { + SmallString<40> Separator; + raw_svector_ostream OS(Separator); + if (ShouldClosePacket) { + OS << " }"; + if (IsLoop0 || IsLoop1) + OS << " "; + if (IsLoop0) + OS << (IsLoop1 ? ":endloop01" : ":endloop0"); + else if (IsLoop1) + OS << ":endloop1"; + } + OS << '\n'; + return OS.str().str(); + } + + void emitPostInstructionInfo(formatted_raw_ostream &FOS, const MCAsmInfo &MAI, + const MCSubtargetInfo &STI, StringRef Comments, + LiveVariablePrinter &LVP) override { + // Hexagon does not write anything to the comment stream, so we can just + // print the separator. + LVP.printAfterInst(FOS); + FOS << getInstructionSeparator(); + FOS.flush(); + if (ShouldClosePacket) + reset(); + } + void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef Bytes, object::SectionedAddress Address, formatted_raw_ostream &OS, StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP, @@ -724,60 +783,64 @@ class HexagonPrettyPrinter : public PrettyPrinter { if (!MI) { printLead(Bytes, Address.Address, OS); OS << " "; + reset(); return; } - std::string Buffer; + + StringRef Preamble = IsStartOfBundle ? " { " : " "; + + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ObjectFilename, LVP, ""); + printLead(Bytes, Address.Address, OS); + OS << Preamble; + std::string Buf; { - raw_string_ostream TempStream(Buffer); + raw_string_ostream TempStream(Buf); IP.printInst(MI, Address.Address, "", STI, TempStream); } - StringRef Contents(Buffer); - // Split off bundle attributes - auto PacketBundle = Contents.rsplit('\n'); - // Split off first instruction from the rest - auto HeadTail = PacketBundle.first.split('\n'); - auto Preamble = " { "; - auto Separator = ""; - - // Hexagon's packets require relocations to be inline rather than - // clustered at the end of the packet. - std::vector::const_iterator RelCur = Rels->begin(); - std::vector::const_iterator RelEnd = Rels->end(); - auto PrintReloc = [&]() -> void { - while ((RelCur != RelEnd) && (RelCur->getOffset() <= Address.Address)) { - if (RelCur->getOffset() == Address.Address) { - printRelocation(OS, ObjectFilename, *RelCur, Address.Address, false); - return; - } - ++RelCur; - } - }; + StringRef Contents(Buf); + + auto Duplex = Contents.split('\v'); + bool HasDuplex = !Duplex.second.empty(); + if (HasDuplex) { + OS << Duplex.first; + OS << "; "; + OS << Duplex.second; + } else { + OS << Duplex.first; + } - while (!HeadTail.first.empty()) { - OS << Separator; - Separator = "\n"; - if (SP && (PrintSource || PrintLines)) - SP->printSourceLine(OS, Address, ObjectFilename, LVP, ""); - printLead(Bytes, Address.Address, OS); - OS << Preamble; - Preamble = " "; - StringRef Inst; - auto Duplex = HeadTail.first.split('\v'); - if (!Duplex.second.empty()) { - OS << Duplex.first; - OS << "; "; - Inst = Duplex.second; - } + uint32_t Instruction = support::endian::read32le(Bytes.data()); + + uint32_t ParseMask = 0x0000c000; + uint32_t PacketEndMask = 0x0000c000; + uint32_t LoopEndMask = 0x00008000; + uint32_t ParseBits = Instruction & ParseMask; + + if (ParseBits == LoopEndMask) { + if (IsStartOfBundle) + IsLoop0 = true; else - Inst = HeadTail.first; - OS << Inst; - HeadTail = HeadTail.second.split('\n'); - if (HeadTail.first.empty()) - OS << " } " << PacketBundle.second; - PrintReloc(); - Bytes = Bytes.slice(4); - Address.Address += 4; + IsLoop1 = true; } + + IsStartOfBundle = false; + + if (ParseBits == PacketEndMask || HasDuplex) + ShouldClosePacket = true; + } + +private: + bool IsStartOfBundle = true; + bool IsLoop0 = false; + bool IsLoop1 = false; + bool ShouldClosePacket = false; + + void reset() { + IsStartOfBundle = true; + IsLoop0 = false; + IsLoop1 = false; + ShouldClosePacket = false; } }; HexagonPrettyPrinter HexagonPrettyPrinterInst; @@ -1610,29 +1673,6 @@ static StringRef getSegmentName(const MachOObjectFile *MachO, return ""; } -static void emitPostInstructionInfo(formatted_raw_ostream &FOS, - const MCAsmInfo &MAI, - const MCSubtargetInfo &STI, - StringRef Comments, - LiveVariablePrinter &LVP) { - do { - if (!Comments.empty()) { - // Emit a line of comments. - StringRef Comment; - std::tie(Comment, Comments) = Comments.split('\n'); - // MAI.getCommentColumn() assumes that instructions are printed at the - // position of 8, while getInstStartColumn() returns the actual position. - unsigned CommentColumn = - MAI.getCommentColumn() - 8 + getInstStartColumn(STI); - FOS.PadToColumn(CommentColumn); - FOS << MAI.getCommentString() << ' ' << Comment; - } - LVP.printAfterInst(FOS); - FOS << '\n'; - } while (!Comments.empty()); - FOS.flush(); -} - static void createFakeELFSections(ObjectFile &Obj) { assert(Obj.isELF()); if (auto *Elf32LEObj = dyn_cast(&Obj)) @@ -2182,6 +2222,8 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, Start += Size; break; } + // Allow targets to reset any per-symbol state. + DT->Printer->onSymbolStart(); formatted_raw_ostream FOS(OS); Index = Start; if (SectionAddr < StartAddress) @@ -2526,15 +2568,15 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, } assert(DT->Context->getAsmInfo()); - emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(), - *DT->SubtargetInfo, CommentStream.str(), LVP); + DT->Printer->emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(), + *DT->SubtargetInfo, + CommentStream.str(), LVP); Comments.clear(); if (BTF) printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LVP); - // Hexagon handles relocs in pretty printer - if (InlineRelocs && Obj.getArch() != Triple::hexagon) { + if (InlineRelocs) { while (findRel()) { // When --adjust-vma is used, update the address printed. printRelocation(FOS, Obj.getFileName(), *RelCur, diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 101079f09e1d2..3fd167df1ecc5 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1083,26 +1083,26 @@ const EnumEntry ElfObjectFileType[] = { }; const EnumEntry ElfOSABI[] = { - {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, - {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, - {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, - {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, - {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, - {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, - {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, - {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, - {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, - {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, - {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, - {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, - {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, - {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, - {"AROS", "AROS", ELF::ELFOSABI_AROS}, - {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, - {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, - {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA}, - {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE} -}; + {"SystemV", "UNIX - System V", ELF::ELFOSABI_NONE}, + {"HPUX", "UNIX - HP-UX", ELF::ELFOSABI_HPUX}, + {"NetBSD", "UNIX - NetBSD", ELF::ELFOSABI_NETBSD}, + {"GNU/Linux", "UNIX - GNU", ELF::ELFOSABI_LINUX}, + {"GNU/Hurd", "GNU/Hurd", ELF::ELFOSABI_HURD}, + {"Solaris", "UNIX - Solaris", ELF::ELFOSABI_SOLARIS}, + {"AIX", "UNIX - AIX", ELF::ELFOSABI_AIX}, + {"IRIX", "UNIX - IRIX", ELF::ELFOSABI_IRIX}, + {"FreeBSD", "UNIX - FreeBSD", ELF::ELFOSABI_FREEBSD}, + {"TRU64", "UNIX - TRU64", ELF::ELFOSABI_TRU64}, + {"Modesto", "Novell - Modesto", ELF::ELFOSABI_MODESTO}, + {"OpenBSD", "UNIX - OpenBSD", ELF::ELFOSABI_OPENBSD}, + {"OpenVMS", "VMS - OpenVMS", ELF::ELFOSABI_OPENVMS}, + {"NSK", "HP - Non-Stop Kernel", ELF::ELFOSABI_NSK}, + {"AROS", "AROS", ELF::ELFOSABI_AROS}, + {"FenixOS", "FenixOS", ELF::ELFOSABI_FENIXOS}, + {"CloudABI", "CloudABI", ELF::ELFOSABI_CLOUDABI}, + {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA}, + {"CUDA", "NVIDIA - CUDA", ELF::ELFOSABI_CUDA_V2}, + {"Standalone", "Standalone App", ELF::ELFOSABI_STANDALONE}}; const EnumEntry AMDGPUElfOSABI[] = { {"AMDGPU_HSA", "AMDGPU - HSA", ELF::ELFOSABI_AMDGPU_HSA}, @@ -1666,16 +1666,60 @@ const EnumEntry ElfHeaderAMDGPUFlagsABIVersion4[] = { }; const EnumEntry ElfHeaderNVPTXFlags[] = { - ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"), - ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"), - ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"), - ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"), - ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"), - ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"), - ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"), - ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"), - ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"), - ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"), + ENUM_ENT(EF_CUDA_SM20, "sm_20"), + ENUM_ENT(EF_CUDA_SM21, "sm_21"), + ENUM_ENT(EF_CUDA_SM30, "sm_30"), + ENUM_ENT(EF_CUDA_SM32, "sm_32"), + ENUM_ENT(EF_CUDA_SM35, "sm_35"), + ENUM_ENT(EF_CUDA_SM37, "sm_37"), + ENUM_ENT(EF_CUDA_SM50, "sm_50"), + ENUM_ENT(EF_CUDA_SM52, "sm_52"), + ENUM_ENT(EF_CUDA_SM53, "sm_53"), + ENUM_ENT(EF_CUDA_SM60, "sm_60"), + ENUM_ENT(EF_CUDA_SM61, "sm_61"), + ENUM_ENT(EF_CUDA_SM62, "sm_62"), + ENUM_ENT(EF_CUDA_SM70, "sm_70"), + ENUM_ENT(EF_CUDA_SM72, "sm_72"), + ENUM_ENT(EF_CUDA_SM75, "sm_75"), + ENUM_ENT(EF_CUDA_SM80, "sm_80"), + ENUM_ENT(EF_CUDA_SM86, "sm_86"), + ENUM_ENT(EF_CUDA_SM87, "sm_87"), + ENUM_ENT(EF_CUDA_SM88, "sm_88"), + ENUM_ENT(EF_CUDA_SM89, "sm_89"), + ENUM_ENT(EF_CUDA_SM90, "sm_90"), + ENUM_ENT(EF_CUDA_SM100, "sm_100"), + ENUM_ENT(EF_CUDA_SM101, "sm_101"), + ENUM_ENT(EF_CUDA_SM103, "sm_103"), + ENUM_ENT(EF_CUDA_SM110, "sm_110"), + ENUM_ENT(EF_CUDA_SM120, "sm_120"), + ENUM_ENT(EF_CUDA_SM121, "sm_121"), + ENUM_ENT(EF_CUDA_SM20 << EF_CUDA_SM_OFFSET, "sm_20"), + ENUM_ENT(EF_CUDA_SM21 << EF_CUDA_SM_OFFSET, "sm_21"), + ENUM_ENT(EF_CUDA_SM30 << EF_CUDA_SM_OFFSET, "sm_30"), + ENUM_ENT(EF_CUDA_SM32 << EF_CUDA_SM_OFFSET, "sm_32"), + ENUM_ENT(EF_CUDA_SM35 << EF_CUDA_SM_OFFSET, "sm_35"), + ENUM_ENT(EF_CUDA_SM37 << EF_CUDA_SM_OFFSET, "sm_37"), + ENUM_ENT(EF_CUDA_SM50 << EF_CUDA_SM_OFFSET, "sm_50"), + ENUM_ENT(EF_CUDA_SM52 << EF_CUDA_SM_OFFSET, "sm_52"), + ENUM_ENT(EF_CUDA_SM53 << EF_CUDA_SM_OFFSET, "sm_53"), + ENUM_ENT(EF_CUDA_SM60 << EF_CUDA_SM_OFFSET, "sm_60"), + ENUM_ENT(EF_CUDA_SM61 << EF_CUDA_SM_OFFSET, "sm_61"), + ENUM_ENT(EF_CUDA_SM62 << EF_CUDA_SM_OFFSET, "sm_62"), + ENUM_ENT(EF_CUDA_SM70 << EF_CUDA_SM_OFFSET, "sm_70"), + ENUM_ENT(EF_CUDA_SM72 << EF_CUDA_SM_OFFSET, "sm_72"), + ENUM_ENT(EF_CUDA_SM75 << EF_CUDA_SM_OFFSET, "sm_75"), + ENUM_ENT(EF_CUDA_SM80 << EF_CUDA_SM_OFFSET, "sm_80"), + ENUM_ENT(EF_CUDA_SM86 << EF_CUDA_SM_OFFSET, "sm_86"), + ENUM_ENT(EF_CUDA_SM87 << EF_CUDA_SM_OFFSET, "sm_87"), + ENUM_ENT(EF_CUDA_SM88 << EF_CUDA_SM_OFFSET, "sm_88"), + ENUM_ENT(EF_CUDA_SM89 << EF_CUDA_SM_OFFSET, "sm_89"), + ENUM_ENT(EF_CUDA_SM90 << EF_CUDA_SM_OFFSET, "sm_90"), + ENUM_ENT(EF_CUDA_SM100 << EF_CUDA_SM_OFFSET, "sm_100"), + ENUM_ENT(EF_CUDA_SM101 << EF_CUDA_SM_OFFSET, "sm_101"), + ENUM_ENT(EF_CUDA_SM103 << EF_CUDA_SM_OFFSET, "sm_103"), + ENUM_ENT(EF_CUDA_SM110 << EF_CUDA_SM_OFFSET, "sm_110"), + ENUM_ENT(EF_CUDA_SM120 << EF_CUDA_SM_OFFSET, "sm_120"), + ENUM_ENT(EF_CUDA_SM121 << EF_CUDA_SM_OFFSET, "sm_121"), }; const EnumEntry ElfHeaderRISCVFlags[] = { @@ -3650,10 +3694,16 @@ template void GNUELFDumper::printFileHeaders() { else if (e.e_machine == EM_XTENSA) ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags), unsigned(ELF::EF_XTENSA_MACH)); - else if (e.e_machine == EM_CUDA) + else if (e.e_machine == EM_CUDA) { ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags), unsigned(ELF::EF_CUDA_SM)); - else if (e.e_machine == EM_AMDGPU) { + if (e.e_ident[ELF::EI_ABIVERSION] == ELF::ELFABIVERSION_CUDA_V1 && + (e.e_flags & ELF::EF_CUDA_ACCELERATORS_V1)) + ElfFlags += "a"; + else if (e.e_ident[ELF::EI_ABIVERSION] == ELF::ELFABIVERSION_CUDA_V2 && + (e.e_flags & ELF::EF_CUDA_ACCELERATORS)) + ElfFlags += "a"; + } else if (e.e_machine == EM_AMDGPU) { switch (e.e_ident[ELF::EI_ABIVERSION]) { default: break; diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 7a48105a1dc99..bf396499e35ca 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/FloatingPointMode.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/FloatingPointPredicateUtils.h" #include "llvm/AsmParser/Parser.h" @@ -2208,6 +2209,41 @@ TEST_F(ComputeKnownFPClassTest, Constants) { } } +TEST_F(ComputeKnownFPClassTest, fcmpImpliesClass_fabs_zero) { + parseAssembly("define float @test(float %x) {\n" + " %A = call float @llvm.fabs.f32(float %x)\n" + " ret float %A\n" + "}\n"); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OEQ, *F, A, fcZero)), + fcZero); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UEQ, *F, A, fcZero)), + fcZero | fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNE, *F, A, fcZero)), + ~fcZero); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ONE, *F, A, fcZero)), + ~fcNan & ~fcZero); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ORD, *F, A, fcZero)), + ~fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UNO, *F, A, fcZero)), + fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGT, *F, A, fcZero)), + fcSubnormal | fcNormal | fcInf); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGT, *F, A, fcZero)), + fcSubnormal | fcNormal | fcInf | fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OGE, *F, A, fcZero)), + ~fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_UGE, *F, A, fcZero)), + fcAllFlags); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLT, *F, A, fcZero)), + fcNone); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULT, *F, A, fcZero)), + fcNan); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_OLE, *F, A, fcZero)), + fcZero); + EXPECT_EQ(std::get<1>(fcmpImpliesClass(FCmpInst::FCMP_ULE, *F, A, fcZero)), + fcZero | fcNan); +} + TEST_F(ValueTrackingTest, isNonZeroRecurrence) { parseAssembly(R"( define i1 @test(i8 %n, i8 %r) { diff --git a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn index 8f7beea152ab7..30b8bb61184bd 100644 --- a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn @@ -87,6 +87,7 @@ shared_library("libclang") { "Index_Internal.h", "Indexing.cpp", "Rewrite.cpp", + "Obsolete.cpp", ] if (host_os == "mac") { ldflags = [ diff --git a/llvm/utils/gn/secondary/llvm/version.gni b/llvm/utils/gn/secondary/llvm/version.gni index 2b1a9076afe4a..8c7f81568cd5e 100644 --- a/llvm/utils/gn/secondary/llvm/version.gni +++ b/llvm/utils/gn/secondary/llvm/version.gni @@ -1,4 +1,4 @@ llvm_version_major = 21 -llvm_version_minor = 0 -llvm_version_patch = 0 +llvm_version_minor = 1 +llvm_version_patch = 8 llvm_version = "$llvm_version_major.$llvm_version_minor.$llvm_version_patch" diff --git a/llvm/utils/lit/lit/__init__.py b/llvm/utils/lit/lit/__init__.py index b5aa8edc03dc7..1be36556e4f73 100644 --- a/llvm/utils/lit/lit/__init__.py +++ b/llvm/utils/lit/lit/__init__.py @@ -2,7 +2,7 @@ __author__ = "Daniel Dunbar" __email__ = "daniel@minormatter.com" -__versioninfo__ = (21, 0, 0) +__versioninfo__ = (21, 1, 8) __version__ = ".".join(str(v) for v in __versioninfo__) + "dev" __all__ = [] diff --git a/llvm/utils/mlgo-utils/mlgo/__init__.py b/llvm/utils/mlgo-utils/mlgo/__init__.py index d3369abae70b9..76e2671a0e567 100644 --- a/llvm/utils/mlgo-utils/mlgo/__init__.py +++ b/llvm/utils/mlgo-utils/mlgo/__init__.py @@ -4,7 +4,7 @@ from datetime import timezone, datetime -__versioninfo__ = (20, 0, 0) +__versioninfo__ = (21, 1, 8) __version__ = ( ".".join(str(v) for v in __versioninfo__) + "dev" diff --git a/llvm/utils/release/build_llvm_release.bat b/llvm/utils/release/build_llvm_release.bat index 3042fc2d77dd1..54645d0c6369f 100755 --- a/llvm/utils/release/build_llvm_release.bat +++ b/llvm/utils/release/build_llvm_release.bat @@ -169,9 +169,9 @@ set common_cmake_flags=^ if "%force-msvc%" == "" ( where /q clang-cl - if errorlevel 0 ( + if %errorlevel% EQU 0 ( where /q lld-link - if errorlevel 0 ( + if %errorlevel% EQU 0 ( set common_compiler_flags=%common_compiler_flags% -fuse-ld=lld set common_cmake_flags=%common_cmake_flags%^ diff --git a/llvm/utils/release/export.sh b/llvm/utils/release/export.sh index 66bef82586a34..0ac392cbed7be 100755 --- a/llvm/utils/release/export.sh +++ b/llvm/utils/release/export.sh @@ -123,7 +123,7 @@ export_sources() { tar -C test-suite-$release$rc.src --strip-components=1 -xzf - fi echo "Creating tarball for test-suite ..." - tar --sort=name --owner=0 --group=0 \ + XZ_OPT="-T0" tar --sort=name --owner=0 --group=0 \ --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \ -cJf test-suite-$release$rc.src.tar.xz test-suite-$release$rc.src fi diff --git a/llvm/utils/release/github-upload-release.py b/llvm/utils/release/github-upload-release.py index 90c222d1175c7..d58bb544e17dd 100755 --- a/llvm/utils/release/github-upload-release.py +++ b/llvm/utils/release/github-upload-release.py @@ -45,19 +45,39 @@ def create_release(repo, release, tag=None, name=None, message=None): # Note that these lines are not length limited because if we do so, GitHub # assumes that should be how it is laid out on the page. We want GitHub to # do the reflowing for us instead. + # + # Once all the atuomatic binary builds have completed, the HTML comments + # with UPPERCASE markers in them will be removed to reveal the download + # links later. Other lines are surrounded in for release uploaders + # to manually uncomment when they upload that package. message = dedent( """\ -LLVM {release} Release +## LLVM {release} Release -## Package Types + + -Each platform has one binary release package. The file name starts with either `LLVM-` or `clang+llvm-` and ends with the platform's name. For example, `LLVM-{release}-Linux-ARM64.tar.xz` contains LLVM binaries for Arm64 Linux. + + + + + -Except for Windows. Where `LLVM-*.exe` is an installer intended for using LLVM as a toolchain and `clang+llvm-` contains the contents of the installer, plus libraries and tools not normally used in a toolchain. You most likely want the `LLVM-` installer, unless you are developing software which itself uses LLVM, in which case choose `clang+llvm-`. +Download links will appear here once builds have completed. + +For any other variants of platform and architecture, check the full list of release packages at the bottom of this release page. If you do not find a release package for your platform, you may be able to find a community built package on the LLVM Discourse forum thread for this release. Remember that these are built by volunteers and may not always be available. If you rely on a platform or configuration that is not one of the defaults, we suggest you use the binaries that your platform provides, or build your own release packages. + +## Package Types -If you do not find a release package for your platform, you may be able to find a community built package on the LLVM Discourse forum thread for this release. Remember that these are built by volunteers and may not always be available. +Each platform has one binary release package. The file name starts with either `LLVM-` or `clang+llvm-` and ends with the platform's name. For example, `LLVM-{release}-Linux-ARM64.tar.xz` contains LLVM binaries for Arm64 Linux. -If you rely on a platform or configuration that is not one of the defaults, we suggest you use the binaries that your platform provides, or build your own release packages. +Except for Windows. Where `LLVM-*.exe` is an installer intended for using LLVM as a toolchain and the archive `clang+llvm-` contains the contents of the installer, plus libraries and tools not normally used in a toolchain. You most likely want the `LLVM-` installer, unless you are developing software which itself uses LLVM, in which case choose `clang+llvm-`. In addition, source archives are available: * `-{release}.src.tar.xz` are archives of the sources of specific sub-projects of `llvm-project` (except for `test-suite` which is an archive of the [LLVM Test Suite](https://github.com/llvm/llvm-test-suite)). @@ -95,9 +115,35 @@ def upload_files(repo, release, files): print("Done") +def uncomment_download_links(repo, release): + release = repo.get_release("llvmorg-{}".format(release)) + + new_message = [] + to_remove = [ + "AUTOMATIC_DOWNLOAD_LINKS_BEGIN", + "AUTOMATIC_DOWNLOAD_LINKS_END", + "AUTOMATIC_DOWNLOAD_LINKS_PLACEHOLDER", + ] + for line in release.body.splitlines(): + for comment in to_remove: + if comment in line: + break + else: + new_message.append(line) + + release.update_release( + name=release.title, + message="\n".join(new_message), + draft=release.draft, + prerelease=release.prerelease, + ) + + parser = argparse.ArgumentParser() parser.add_argument( - "command", type=str, choices=["create", "upload", "check-permissions"] + "command", + type=str, + choices=["create", "upload", "check-permissions", "uncomment_download_links"], ) # All args @@ -137,3 +183,5 @@ def upload_files(repo, release, files): create_release(llvm_repo, args.release) if args.command == "upload": upload_files(llvm_repo, args.release, args.files) +if args.command == "uncomment_download_links": + uncomment_download_links(llvm_repo, args.release) diff --git a/mlir/cmake/modules/AddMLIR.cmake b/mlir/cmake/modules/AddMLIR.cmake index ff4269ed7acd2..c0b360035d739 100644 --- a/mlir/cmake/modules/AddMLIR.cmake +++ b/mlir/cmake/modules/AddMLIR.cmake @@ -204,6 +204,15 @@ function(add_mlir_interface interface) endfunction() +# Declare a dialect in the include directory +function(add_mlir_type_interface interface) + set(LLVM_TARGET_DEFINITIONS ${interface}.td) + mlir_tablegen(${interface}.h.inc -gen-type-interface-decls) + mlir_tablegen(${interface}.cpp.inc -gen-type-interface-defs) + add_public_tablegen_target(MLIR${interface}IncGen) + add_dependencies(mlir-generic-headers MLIR${interface}IncGen) +endfunction() + # Generate Documentation function(add_mlir_doc doc_filename output_file output_directory command) set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td) @@ -388,6 +397,9 @@ function(add_mlir_library name) if(TARGET ${name}) target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS}) + if(ARG_INSTALL_WITH_TOOLCHAIN) + set_target_properties(${name} PROPERTIES MLIR_INSTALL_WITH_TOOLCHAIN TRUE) + endif() if(NOT ARG_DISABLE_INSTALL) add_mlir_library_install(${name}) endif() @@ -617,26 +629,27 @@ endfunction(add_mlir_aggregate) # This is usually done as part of add_mlir_library but is broken out for cases # where non-standard library builds can be installed. function(add_mlir_library_install name) - if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) - get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries) - install(TARGETS ${name} - COMPONENT ${name} - ${export_to_mlirtargets} - LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - # Note that CMake will create a directory like: - # objects-${CMAKE_BUILD_TYPE}/obj.LibName - # and put object files there. - OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ) + get_target_property(_install_with_toolchain ${name} MLIR_INSTALL_WITH_TOOLCHAIN) + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR _install_with_toolchain) + get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries) + install(TARGETS ${name} + COMPONENT ${name} + ${export_to_mlirtargets} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + # Note that CMake will create a directory like: + # objects-${CMAKE_BUILD_TYPE}/obj.LibName + # and put object files there. + OBJECTS DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ) - if (NOT LLVM_ENABLE_IDE) - add_llvm_install_targets(install-${name} - DEPENDS ${name} - COMPONENT ${name}) - endif() - set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name}) + if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(install-${name} + DEPENDS ${name} + COMPONENT ${name}) + endif() + set_property(GLOBAL APPEND PROPERTY MLIR_ALL_LIBS ${name}) endif() set_property(GLOBAL APPEND PROPERTY MLIR_EXPORTS ${name}) endfunction() diff --git a/mlir/docs/DefiningDialects/AttributesAndTypes.md b/mlir/docs/DefiningDialects/AttributesAndTypes.md index 022bdad9fe512..fde737f51356a 100644 --- a/mlir/docs/DefiningDialects/AttributesAndTypes.md +++ b/mlir/docs/DefiningDialects/AttributesAndTypes.md @@ -565,6 +565,11 @@ For Attributes, these methods will have the form: - `void MyAttr::print(AsmPrinter &p) const` +It is possible to use newlines and indents in custom `print` methods. +However, multiline Types or Attributes are not recommended nor allowed in the upstream MLIR dialects. +They can be used in custom dialects to improve flexibility and readability, e.g. in cases of +multiple nested Types and Attributes. + #### Using `assemblyFormat` Attributes and types defined in ODS with a mnemonic can define an diff --git a/mlir/include/mlir/Analysis/DataFlowFramework.h b/mlir/include/mlir/Analysis/DataFlowFramework.h index 49862927caff2..e364570c8b531 100644 --- a/mlir/include/mlir/Analysis/DataFlowFramework.h +++ b/mlir/include/mlir/Analysis/DataFlowFramework.h @@ -354,29 +354,7 @@ class DataFlowSolver { /// Erase any analysis state associated with the given lattice anchor. template - void eraseState(AnchorT anchor) { - LatticeAnchor latticeAnchor(anchor); - - // Update equivalentAnchorMap. - for (auto &&[TypeId, eqClass] : equivalentAnchorMap) { - if (!eqClass.contains(latticeAnchor)) { - continue; - } - llvm::EquivalenceClasses::member_iterator leaderIt = - eqClass.findLeader(latticeAnchor); - - // Update analysis states with new leader if needed. - if (*leaderIt == latticeAnchor && ++leaderIt != eqClass.member_end()) { - analysisStates[*leaderIt][TypeId] = - std::move(analysisStates[latticeAnchor][TypeId]); - } - - eqClass.erase(latticeAnchor); - } - - // Update analysis states. - analysisStates.erase(latticeAnchor); - } + void eraseState(AnchorT anchor); /// Erase all analysis states. void eraseAllStates() { @@ -560,6 +538,36 @@ class AnalysisState { friend class DataFlowSolver; }; +//===----------------------------------------------------------------------===// +// DataFlowSolver definition +//===----------------------------------------------------------------------===// +// This method is defined outside `DataFlowSolver` and after `AnalysisState` +// to prevent issues around `AnalysisState` being used before it is defined. +template +void DataFlowSolver::eraseState(AnchorT anchor) { + LatticeAnchor latticeAnchor(anchor); + + // Update equivalentAnchorMap. + for (auto &&[TypeId, eqClass] : equivalentAnchorMap) { + if (!eqClass.contains(latticeAnchor)) { + continue; + } + llvm::EquivalenceClasses::member_iterator leaderIt = + eqClass.findLeader(latticeAnchor); + + // Update analysis states with new leader if needed. + if (*leaderIt == latticeAnchor && ++leaderIt != eqClass.member_end()) { + analysisStates[*leaderIt][TypeId] = + std::move(analysisStates[latticeAnchor][TypeId]); + } + + eqClass.erase(latticeAnchor); + } + + // Update analysis states. + analysisStates.erase(latticeAnchor); +} + //===----------------------------------------------------------------------===// // DataFlowAnalysis //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Analysis/SliceAnalysis.h b/mlir/include/mlir/Analysis/SliceAnalysis.h index d082d2d9f758b..18349d071bb2e 100644 --- a/mlir/include/mlir/Analysis/SliceAnalysis.h +++ b/mlir/include/mlir/Analysis/SliceAnalysis.h @@ -65,8 +65,9 @@ using ForwardSliceOptions = SliceOptions; /// /// The implementation traverses the use chains in postorder traversal for /// efficiency reasons: if an operation is already in `forwardSlice`, no -/// need to traverse its uses again. Since use-def chains form a DAG, this -/// terminates. +/// need to traverse its uses again. In the presence of use-def cycles in a +/// graph region, the traversal stops at the first operation that was already +/// visited (which is not added to the slice anymore). /// /// Upon return to the root call, `forwardSlice` is filled with a /// postorder list of uses (i.e. a reverse topological order). To get a proper @@ -114,8 +115,9 @@ void getForwardSlice(Value root, SetVector *forwardSlice, /// /// The implementation traverses the def chains in postorder traversal for /// efficiency reasons: if an operation is already in `backwardSlice`, no -/// need to traverse its definitions again. Since useuse-def chains form a DAG, -/// this terminates. +/// need to traverse its definitions again. In the presence of use-def cycles +/// in a graph region, the traversal stops at the first operation that was +/// already visited (which is not added to the slice anymore). /// /// Upon return to the root call, `backwardSlice` is filled with a /// postorder list of defs. This happens to be a topological order, from the diff --git a/mlir/include/mlir/AsmParser/AsmParser.h b/mlir/include/mlir/AsmParser/AsmParser.h index 33daf7ca26f49..f39b3bd853a2a 100644 --- a/mlir/include/mlir/AsmParser/AsmParser.h +++ b/mlir/include/mlir/AsmParser/AsmParser.h @@ -53,7 +53,8 @@ parseAsmSourceFile(const llvm::SourceMgr &sourceMgr, Block *block, /// null terminated. Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type = {}, size_t *numRead = nullptr, - bool isKnownNullTerminated = false); + bool isKnownNullTerminated = false, + llvm::StringMap *attributesCache = nullptr); /// This parses a single MLIR type to an MLIR context if it was valid. If not, /// an error diagnostic is emitted to the context. diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h index 6245f88db3d19..6ecf4a291cfc6 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h @@ -260,12 +260,12 @@ struct BufferizationOptions { std::function; /// Initializer function for analysis state. using AnalysisStateInitFn = std::function; - /// Tensor -> MemRef type converter. - /// Parameters: tensor type, memory space, func op, bufferization options + /// Tensor-like -> Buffer-like type conversion. + /// Parameters: tensor-like type, memory space, func op, bufferization options using FunctionArgTypeConverterFn = - std::function; - /// Tensor -> MemRef type converter. + /// Tensor -> MemRef type conversion. /// Parameters: tensor type, memory space, bufferization options using UnknownTypeConverterFn = std::function; @@ -335,10 +335,12 @@ struct BufferizationOptions { /// predictable. void setFunctionBoundaryTypeConversion(LayoutMapOption layoutMapOption); - /// Type converter from tensors to memrefs. This type converter is used to - /// determine bufferized function argument and result types. By default, a - /// type converter that returns a memref type with a fully dynamic layout map - /// is used. + /// Type conversion from tensors to buffers. This type conversion is used to + /// determine bufferized function argument and result types. + /// + /// By default, if tensor is a (builtin) tensor type, it is converted to a + /// memref type with a fully dynamic layout map; if tensor is a (generic) + /// tensor-like type, it is converted using TensorLikeType::getBufferType(). /// /// If `bufferizeFunctionBoundaries` is not set, this function isn't used. FunctionArgTypeConverterFn functionArgTypeConverterFn = nullptr; @@ -350,10 +352,9 @@ struct BufferizationOptions { /// If `bufferizeFunctionBoundaries` is not set, this flag has no effect. bool inferFunctionResultLayout = true; - /// Type converter from tensors to memrefs. This type converter is used if no - /// memref type could be inferred during bufferization. By default, a type - /// converter that returns a memref type with a fully dynamic layout map is - /// used. + /// Type conversion from tensors to memrefs. This type conversion is used if + /// no memref type could be inferred during bufferization. By default, returns + /// a memref type with a fully dynamic layout map. UnknownTypeConverterFn unknownTypeConverterFn = nullptr; // Use during type conversion to determine the memory space for memref based diff --git a/mlir/include/mlir/Dialect/Mesh/Transforms/Simplifications.h b/mlir/include/mlir/Dialect/Mesh/Transforms/Simplifications.h index 3f1041cb25103..243dbf081b999 100644 --- a/mlir/include/mlir/Dialect/Mesh/Transforms/Simplifications.h +++ b/mlir/include/mlir/Dialect/Mesh/Transforms/Simplifications.h @@ -62,9 +62,11 @@ void populateAllReduceEndomorphismSimplificationPatterns( auto isEndomorphismOp = [reduction](Operation *op, std::optional referenceOp) { auto allReduceOp = llvm::dyn_cast(op); + if (!allReduceOp) + return false; auto inType = cast(allReduceOp.getInput().getType()); auto outType = cast(allReduceOp.getResult().getType()); - if (!allReduceOp || inType.getElementType() != outType.getElementType() || + if (inType.getElementType() != outType.getElementType() || allReduceOp.getReduction() != reduction) { return false; } @@ -87,9 +89,7 @@ void populateAllReduceEndomorphismSimplificationPatterns( return refAllReduceOp->getAttrs() == allReduceOp->getAttrs() && inType.getElementType() == refType.getElementType(); }; - auto isAlgebraicOp = [](Operation *op) { - return static_cast(llvm::dyn_cast(op)); - }; + auto isAlgebraicOp = [](Operation *op) { return isa(op); }; using ConcreteEndomorphismSimplification = EndomorphismSimplification< std::decay_t, diff --git a/mlir/include/mlir/Dialect/Quant/IR/Quant.h b/mlir/include/mlir/Dialect/Quant/IR/Quant.h index 11a969a3ee519..eb207e8054c9b 100644 --- a/mlir/include/mlir/Dialect/Quant/IR/Quant.h +++ b/mlir/include/mlir/Dialect/Quant/IR/Quant.h @@ -27,6 +27,7 @@ namespace quant { class QuantizedType; class UniformQuantizedType; class UniformQuantizedPerAxisType; +class QuantileType; } // namespace quant } // namespace mlir diff --git a/mlir/include/mlir/Dialect/Quant/IR/QuantBase.td b/mlir/include/mlir/Dialect/Quant/IR/QuantBase.td index 23bf5cf15e256..ee38716e0d301 100644 --- a/mlir/include/mlir/Dialect/Quant/IR/QuantBase.td +++ b/mlir/include/mlir/Dialect/Quant/IR/QuantBase.td @@ -402,6 +402,26 @@ class quant_ScalarOrTensorOf : def quant_QuantizedType : Type($_self)">, "quantized type">; +// QuantileType +def quant_QuantileType : + DialectType($_self)">, + "QuantileType">; + +// Predicate for detecting a scalar or tensor of QuantileType. +def quant_QuantileValueType : + quant_ScalarOrTensorOf; + +// UniformQuantizedPerAxisType +def quant_UniformQuantizedPerAxisType : + DialectType($_self)">, + "UniformQuantizedPerAxisType">; + +// Predicate for detecting a container or primitive of UniformQuantizedPerAxisType. +def quant_UniformQuantizedPerAxisValueType : + quant_ScalarOrTensorOf; + def quant_ScalarType : Type>>>; def DoubleAPFloatList : List; +def OptionalSignedVarInt: + WithParser <"succeeded(readOptionalSignedVarInt($_reader, $_var))", + WithBuilder<"$_args", + WithPrinter<"writeOptionalSignedVarInt($_writer, $_getter)", + WithType <"std::optional">>>>; + let cType = "AnyQuantizedType" in { def AnyQuantizedType: DialectType<(type @@ -97,6 +103,14 @@ def UniformQuantizedSubChannelType }]; } +def QuantileType : DialectType<(type + Type:$storageType, + Type:$quantileType, + Array:$quantiles, + OptionalSignedVarInt:$storageMin, + OptionalSignedVarInt:$storageMax +)>; + /// This enum contains marker codes used to indicate which attribute is /// currently being decoded, and how it should be decoded. The order of these /// codes should generally be unchanged, as any changes will inevitably break @@ -106,7 +120,7 @@ def QuantDialectTypes : DialectTypes<"Quant"> { let elems = [ReservedOrDead, AnyQuantizedType, AnyQuantizedTypeWithExpressedType, CalibratedQuantizedType, UniformQuantizedType, UniformQuantizedPerAxisType, - UniformQuantizedSubChannelType]; + UniformQuantizedSubChannelType, QuantileType]; } #endif // QUANT_BYTECODE diff --git a/mlir/include/mlir/Dialect/Quant/IR/QuantTypes.h b/mlir/include/mlir/Dialect/Quant/IR/QuantTypes.h index 44062fe376ec0..3f511c5f05565 100644 --- a/mlir/include/mlir/Dialect/Quant/IR/QuantTypes.h +++ b/mlir/include/mlir/Dialect/Quant/IR/QuantTypes.h @@ -27,6 +27,7 @@ struct UniformQuantizedSubChannelTypeStorage; struct UniformQuantizedTypeStorage; struct UniformQuantizedPerAxisTypeStorage; struct CalibratedQuantizedTypeStorage; +struct QuantileTypeStorage; } // namespace detail @@ -83,6 +84,24 @@ class QuantizedType : public Type { return llvm::maxUIntN(integralWidth); } + static constexpr int64_t getDefaultMaximumForF8E4M3FN() { return 448; } + + static constexpr int64_t getDefaultMinimumForF8E4M3FN() { + return -getDefaultMaximumForF8E4M3FN(); + } + + static constexpr int64_t getDefaultMaximumForF8E5M2() { return 57344; } + + static constexpr int64_t getDefaultMinimumForF8E5M2() { + return -getDefaultMaximumForF8E5M2(); + } + + static constexpr int64_t getDefaultMaximumForF4E2M1FN() { return 6; } + + static constexpr int64_t getDefaultMinimumForF4E2M1FN() { + return -getDefaultMaximumForF4E2M1FN(); + } + /// Gets the original expressed type that this quantized type approximates. /// Note that this presumes that the quantized type was always derived from /// a floating point type, which in the broadest definition, is not true (i.e. @@ -253,7 +272,7 @@ class AnyQuantizedType /// Per-layer, optional parameters omitted: /// !quant /// -/// StorageType: 'i'|'u' NumBits +/// StorageType: 'i'|'u' NumBits, 'f4', 'F8E5M2', 'bf8', 'quantile' /// ExpressedType: 'f16', 'f32', 'bf16', 'f64' /// Scale: A legal double value /// ZeroPoint: An integer value @@ -287,6 +306,8 @@ class UniformQuantizedType int64_t zeroPoint, int64_t storageTypeMin, int64_t storageTypeMax); + static bool classof(mlir::Type type); + /// Gets the scale term. The scale designates the difference between the real /// values corresponding to consecutive quantized values differing by 1. double getScale() const; @@ -311,7 +332,7 @@ class UniformQuantizedType /// Per-axis, optional parameters omitted: /// !quant /// -/// StorageType: 'i'|'u' NumBits +/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8', 'quantile' /// ExpressedType: 'f16', 'f32', 'bf16', 'f64' /// QuantizedDim: An integer value /// QuantParams: (Scale ':' ZeroPoint)+ @@ -350,6 +371,8 @@ class UniformQuantizedPerAxisType int32_t quantizedDimension, int64_t storageTypeMin, int64_t storageTypeMax); + static bool classof(mlir::Type type); + /// Gets the quantization scales. The scales designate the difference between /// the real values corresponding to consecutive quantized values differing /// by 1. The ith scale corresponds to the ith slice in the @@ -396,7 +419,7 @@ class UniformQuantizedPerAxisType /// ScaleZeroList ::= ScaleZero (',' ScaleZero)* /// ScaleZero ::= Scale (':' ZeroPoint)? /// -/// StorageType: 'i'|'u' NumBits +/// StorageType: 'i'|'u' NumBits, 'f4', 'hf8', 'bf8', 'quantile' /// ExpressedType: 'f16', 'f32', 'bf16', 'f64' /// AxisSpec: An integer value /// BlockSizeSpec: An integer value @@ -545,6 +568,125 @@ class CalibratedQuantizedType double getMax() const; }; +/*Syntax: + + ``` + quantile-type ::= `!quant.quantile` `<` type `:` type `,` `{` float-list / + int-list `}` + (`,` `<` int `,` int `>`)? `>` + ``` + + A quantile type represents a quantile-based floating point encoding, where + discrete storage values are totally defined by the floating-point or integer + values entries in a quantile lookup table of F8/F16/F32/F64 or integer types. + + Optionally, explicit minimum and maximum storage values can be specified + after the LUT as ``. + + This type is used for weight compression schemes like NF4 (NormalizedFloat4) + and similar quantile-based formats. + + Example: + + MLIR: + !quant.quantile + !quant.quantile> + + As an additional explanation for better understanding and readability of the + above example, the quantile type can be broken down as follows: + - `!quant.quantile`: This indicates that we are defining a quantile type. + - ``: This optional part specifies the explicit minimum and maximum + storage values. In this case, the minimum storage value is -8 and the maximum + storage value is 7. +*/ + +class QuantileType + : public Type::TypeBase { +public: + using ImplType = detail::QuantileTypeStorage; + using Base::Base; + + // Get the underlying type used for to store raw values. + Type getStorageType() const; + + // Get primitive expressed type of data in quantiles. + // Note that we may convert FP8 data to FP16 for storage, + // but we should treat its expressed type as FP8 rather than FP16. + Type getQuantileType() const; + + /// Return the quantile table of this float type. + ArrayRef getQuantiles() const; + + /// Return the explicit storage minimum, if set. + std::optional getStorageMin() const; + + /// Return the explicit storage maximum, if set. + std::optional getStorageMax() const; + + // Get a quantile float type with specified quantile table. + static QuantileType get(mlir::MLIRContext *ctx, Type storageType, + Type quantileType, ArrayRef quantiles = {}, + std::optional storageMin = std::nullopt, + std::optional storageMax = std::nullopt); + + static QuantileType + getChecked(function_ref emitError, + mlir::MLIRContext *ctx, Type storageType, Type quantileType, + ArrayRef quantiles, + std::optional storageMin = std::nullopt, + std::optional storageMax = std::nullopt); + + static LogicalResult verifyInvariants( + function_ref emitError, Type storageType, + Type quantileType, ArrayRef quantiles, + std::optional storageMin, std::optional storageMax); + + /// Methods for support type inquiry through isa, cast, and dyn_cast. + static bool classof(mlir::Type type); + + // Printer + void print(mlir::AsmPrinter &printer) const; + + static constexpr llvm::StringLiteral getMnemonic() { return {"quantile"}; } + + static constexpr llvm::StringLiteral name = "quantile"; + + // Returns true if the type defaults to signed (e.g., si8, i8 or float types), + // false otherwise + bool shouldDefaultToSigned() const; + + // Get the bit width of the storage type. + unsigned getStorageWidth() const; + + // Get the default minimum and maximum values for the storage type. + int64_t getDefaultMinimum([[maybe_unused]] bool isSigned) const; + int64_t getDefaultMaximum([[maybe_unused]] bool isSigned) const; + + // Get the string representation of the storage type + std::string getStorageTypeName([[maybe_unused]] bool isSigned) const; + + // Get whether the type is a packed quantile float type + bool isPacked() const; + + // Get the logical bit width of the quantile float type, which is the bit + // width of the represented floating point value. + unsigned getLogicalBitWidth() const; + + // Get the number of quantized values stored in one byte for this quantile + // float type. + unsigned getElementsPerByte() const; + + // Get the preferred alignment in bytes for this quantile float type, if any. + std::optional getPreferredAlignmentBytes() const; +}; } // namespace quant } // namespace mlir diff --git a/mlir/include/mlir/ExecutionEngine/MemRefUtils.h b/mlir/include/mlir/ExecutionEngine/MemRefUtils.h index 6e72f7c23bdcf..d66d757cb7a8e 100644 --- a/mlir/include/mlir/ExecutionEngine/MemRefUtils.h +++ b/mlir/include/mlir/ExecutionEngine/MemRefUtils.h @@ -151,7 +151,7 @@ class OwningMemRef { AllocFunType allocFun = &::malloc, std::function)> freeFun = [](StridedMemRefType descriptor) { - ::free(descriptor.data); + ::free(descriptor.basePtr); }) : freeFunc(freeFun) { if (shapeAlloc.empty()) diff --git a/mlir/include/mlir/IR/BuiltinTypes.h b/mlir/include/mlir/IR/BuiltinTypes.h index 86ec5c43970b1..d30cba29c9814 100644 --- a/mlir/include/mlir/IR/BuiltinTypes.h +++ b/mlir/include/mlir/IR/BuiltinTypes.h @@ -167,6 +167,8 @@ class BaseMemRefType : public Type, // Tablegen Type Declarations //===----------------------------------------------------------------------===// +#include "mlir/IR/QuantStorageTypeInterface.h" + #define GET_TYPEDEF_CLASSES #include "mlir/IR/BuiltinTypes.h.inc" diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td index a0c8acea91dc5..006e0c75b1f99 100644 --- a/mlir/include/mlir/IR/BuiltinTypes.td +++ b/mlir/include/mlir/IR/BuiltinTypes.td @@ -17,6 +17,7 @@ include "mlir/IR/AttrTypeBase.td" include "mlir/IR/BuiltinDialect.td" include "mlir/IR/BuiltinTypeInterfaces.td" +include "mlir/IR/QuantStorageTypeInterface.td" include "mlir/IR/CommonTypeConstraints.td" // TODO: Currently the types defined in this file are prefixed with `Builtin_`. @@ -80,17 +81,19 @@ def Builtin_Complex : Builtin_Type<"Complex", "complex"> { // Base class for Builtin dialect float types. class Builtin_FloatType traits = [], list declaredInterfaceMethods = []> - : Builtin_Type]> { } // Float types that are cached in MLIRContext. class Builtin_CachedFloatType traits = [], list declaredInterfaceMethods = []> - : Builtin_FloatType { + : Builtin_FloatType { let extraClassDeclaration = [{ static }] # name # [{Type get(MLIRContext *context); }]; @@ -100,7 +103,8 @@ class Builtin_CachedFloatType { +def Builtin_Float8E5M2 : Builtin_FloatType<"Float8E5M2", "f8E5M2", + [QuantStorageTypeInterface]> { let summary = "8-bit floating point with 2 bit mantissa"; let description = [{ An 8-bit floating point type with 1 sign bit, 5 bits exponent and 2 bits @@ -116,6 +120,34 @@ def Builtin_Float8E5M2 : Builtin_FloatType<"Float8E5M2", "f8E5M2"> { Described in: https://arxiv.org/abs/2209.05433 }]; + + let extraClassDeclaration = [{ + /// QuantStorageTypeInterface method implementations + /// Returns true if the the storage type should default to signed + /// when used in quantization. + bool shouldDefaultToSigned() const { return true; } + /// Get the bit width of this 8-bit floating point type. + unsigned getStorageWidth() const { return 8; } + + /// Get default min, max value for this 8-bit floating point type. + int64_t getDefaultMaximum(bool isSigned) const { return 57344; } + int64_t getDefaultMinimum(bool isSigned) const { return -getDefaultMaximum(isSigned); } + + /// Get the storage type as a string. + std::string getStorageTypeName(bool isSigned) const { return "f8E5M2"; } + + /// Check if this 8-bit floating point type uses packed representation. + bool isPacked() const { return false; } + + /// Get the logical bit width per value for this 8-bit floating point type. + unsigned getLogicalBitWidth() const { return 8; } + + /// Returns how many values of this type fit in one byte + unsigned getElementsPerByte() const { return 1; } + + /// Get the preferred alignment in bytes for this 8-bit floating point type. + std::optional getPreferredAlignmentBytes() const { return std::nullopt; } + }]; } //===----------------------------------------------------------------------===// @@ -142,7 +174,8 @@ def Builtin_Float8E4M3 : Builtin_FloatType<"Float8E4M3", "f8E4M3"> { // Float8E4M3FNType //===----------------------------------------------------------------------===// -def Builtin_Float8E4M3FN : Builtin_FloatType<"Float8E4M3FN", "f8E4M3FN"> { +def Builtin_Float8E4M3FN : Builtin_FloatType<"Float8E4M3FN", "f8E4M3FN", + [QuantStorageTypeInterface]> { let summary = "8-bit floating point with 3 bit mantissa"; let description = [{ An 8-bit floating point type with 1 sign bit, 4 bits exponent and 3 bits @@ -159,6 +192,34 @@ def Builtin_Float8E4M3FN : Builtin_FloatType<"Float8E4M3FN", "f8E4M3FN"> { Described in: https://arxiv.org/abs/2209.05433 }]; + + let extraClassDeclaration = [{ + /// QuantStorageTypeInterface method implementations + /// Returns true if the the storage type should default to signed + /// when used in quantization. + bool shouldDefaultToSigned() const { return true; } + /// Get the bit width of this 8-bit floating point type. + unsigned getStorageWidth() const { return 8; } + + /// Get default min, max value for this 8-bit floating point type. + int64_t getDefaultMaximum(bool isSigned) const { return 448; } + int64_t getDefaultMinimum(bool isSigned) const { return -getDefaultMaximum(isSigned); } + + /// Get the storage type as a string. + std::string getStorageTypeName(bool isSigned) const { return "f8E4M3FN"; } + + /// Check if this 8-bit floating point type uses packed representation. + bool isPacked() const { return false; } + + /// Get the logical bit width per value for this 8-bit floating point type. + unsigned getLogicalBitWidth() const { return 8; } + + /// Returns how many values of this type fit in one byte + unsigned getElementsPerByte() const { return 1; } + + /// Get the preferred alignment in bytes for this 8-bit floating point type. + std::optional getPreferredAlignmentBytes() const { return std::nullopt; } + }]; } //===----------------------------------------------------------------------===// @@ -254,7 +315,8 @@ def Builtin_Float8E3M4 : Builtin_FloatType<"Float8E3M4", "f8E3M4"> { // Float4E2M1FNType //===----------------------------------------------------------------------===// -def Builtin_Float4E2M1FN : Builtin_FloatType<"Float4E2M1FN", "f4E2M1FN"> { +def Builtin_Float4E2M1FN : Builtin_FloatType<"Float4E2M1FN", "f4E2M1FN", + [QuantStorageTypeInterface]> { let summary = "4-bit floating point with 2-bit exponent and 1-bit mantissa"; let description = [{ An 4-bit floating point type with 1 sign bit, 2 bits exponent and 1 bit @@ -270,6 +332,34 @@ def Builtin_Float4E2M1FN : Builtin_FloatType<"Float4E2M1FN", "f4E2M1FN"> { Open Compute Project (OCP) microscaling formats (MX) specification: https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf }]; + + let extraClassDeclaration = [{ + /// QuantStorageTypeInterface method implementations + /// Returns true if the the storage type should default to signed + /// when used in quantization. + bool shouldDefaultToSigned() const { return true; } + /// Get the bit width of this 4-bit floating point type. + unsigned getStorageWidth() const { return 4; } + + /// Get default min, max value for this 4-bit floating point type. + int64_t getDefaultMaximum(bool isSigned) const { return 6; } + int64_t getDefaultMinimum(bool isSigned) const { return -getDefaultMaximum(isSigned); } + + /// Get the storage type as a string. + std::string getStorageTypeName(bool isSigned) const { return "f4E2M1FN"; } + + /// Check if this 4-bit floating point type uses packed representation. + bool isPacked() const { return true; } + + /// Get the logical bit width per value for this 4-bit floating point type. + unsigned getLogicalBitWidth() const { return 4; } + + /// Returns how many values of this type fit in one byte + unsigned getElementsPerByte() const { return 2; } + + /// Get the preferred alignment in bytes for this 4-bit floating point type. + std::optional getPreferredAlignmentBytes() const { return std::nullopt; } + }]; } //===----------------------------------------------------------------------===// @@ -345,7 +435,7 @@ def Builtin_Float8E8M0FNU : Builtin_FloatType<"Float8E8M0FNU", "f8E8M0FNU"> { //===----------------------------------------------------------------------===// def Builtin_BFloat16 : Builtin_CachedFloatType<"BFloat16", "bf16", - /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { + /*traits=*/[], /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { let summary = "bfloat16 floating-point type"; } @@ -354,7 +444,7 @@ def Builtin_BFloat16 : Builtin_CachedFloatType<"BFloat16", "bf16", //===----------------------------------------------------------------------===// def Builtin_Float16 : Builtin_CachedFloatType<"Float16", "f16", - /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { + /*traits=*/[], /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { let summary = "16-bit floating-point type"; } @@ -371,7 +461,7 @@ def Builtin_FloatTF32 : Builtin_CachedFloatType<"FloatTF32", "tf32"> { //===----------------------------------------------------------------------===// def Builtin_Float32 : Builtin_CachedFloatType<"Float32", "f32", - /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { + /*traits=*/[], /*declaredInterfaceMethods=*/["scaleElementBitwidth"]> { let summary = "32-bit floating-point type"; } @@ -497,7 +587,7 @@ def Builtin_Index : Builtin_Type<"Index", "index", //===----------------------------------------------------------------------===// def Builtin_Integer : Builtin_Type<"Integer", "integer", - [VectorElementTypeInterface]> { + [VectorElementTypeInterface, QuantStorageTypeInterface]> { let summary = "Integer type with arbitrary precision up to a fixed limit"; let description = [{ Syntax: @@ -554,6 +644,44 @@ def Builtin_Integer : Builtin_Type<"Integer", "integer", /// Integer representation maximal bitwidth. /// Note: This is aligned with the maximum width of llvm::IntegerType. static constexpr unsigned kMaxWidth = (1 << 24) - 1; + + /// QuantStorageTypeInterface method implementations + /// Returns true if the storage type should default to signed when used + /// in quantization. Returns true for signed or signless integer types. + bool shouldDefaultToSigned() const { return !isUnsigned(); } + /// Get the bit width of this integer type. + unsigned getStorageWidth() const { return getWidth(); } + + /// Get default min, max value for this integer type. + int64_t getDefaultMaximum(bool isSigned) const { + if (isSigned) { + return llvm::maxIntN(getWidth()); + } + return llvm::maxUIntN(getWidth()); + } + int64_t getDefaultMinimum(bool isSigned) const { + if (isSigned) { + return llvm::minIntN(getWidth()); + } + return 0; + } + + /// Get the storage type as a string. + std::string getStorageTypeName(bool isSigned) const { + return (isSigned ? "i" : "u") + std::to_string(getWidth()); + } + + /// Check if this integer type uses packed representation. + bool isPacked() const { return getStorageWidth() < 8; } + + /// Get the logical bit width per value for this integer type. + unsigned getLogicalBitWidth() const { return getWidth(); } + + /// Returns how many values of this type fit in one byte + unsigned getElementsPerByte() const { return 8 / getLogicalBitWidth(); } + + /// Get the preferred alignment in bytes for this integer type. + std::optional getPreferredAlignmentBytes() const { return std::nullopt; } }]; } diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt index 846547ff131e3..1e4ca1b8328c6 100644 --- a/mlir/include/mlir/IR/CMakeLists.txt +++ b/mlir/include/mlir/IR/CMakeLists.txt @@ -1,6 +1,8 @@ add_mlir_interface(SymbolInterfaces) add_mlir_interface(RegionKindInterface) +add_mlir_type_interface(QuantStorageTypeInterface) + set(LLVM_TARGET_DEFINITIONS OpAsmInterface.td) mlir_tablegen(OpAsmAttrInterface.h.inc -gen-attr-interface-decls) mlir_tablegen(OpAsmAttrInterface.cpp.inc -gen-attr-interface-defs) diff --git a/mlir/include/mlir/IR/MLIRContext.h b/mlir/include/mlir/IR/MLIRContext.h index ef8dab87f131a..6b13b310b12b4 100644 --- a/mlir/include/mlir/IR/MLIRContext.h +++ b/mlir/include/mlir/IR/MLIRContext.h @@ -257,6 +257,10 @@ class MLIRContext { /// context. A nullptr handler can be set to disable a previously set handler. void registerActionHandler(HandlerTy handler); + /// Return a reference to the currently registered action handler. Its target + /// can be used to gain access to the handler's state, if any. + const HandlerTy &getActionHandler(); + /// Return true if a valid ActionHandler is set. bool hasActionHandler(); diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h index d70aa346eaa1f..a2a4c01f0d2a0 100644 --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -130,6 +130,18 @@ class AsmPrinter { /// Return the raw output stream used by this printer. virtual raw_ostream &getStream() const; + /// Print a newline and indent the printer to the start of the current + /// operation/attribute/type. + /// Note: For attributes and types this method should only be used in + /// custom dialects. Usage in upstream MLIR dialects is currently disallowed. + virtual void printNewline(); + + /// Increase indentation. + virtual void increaseIndent(); + + /// Decrease indentation. + virtual void decreaseIndent(); + /// Print the given floating point value in a stabilized form that can be /// roundtripped through the IR. This is the companion to the 'parseFloat' /// hook on the AsmParser. @@ -448,16 +460,6 @@ class OpAsmPrinter : public AsmPrinter { /// Print a loc(...) specifier if printing debug info is enabled. virtual void printOptionalLocationSpecifier(Location loc) = 0; - /// Print a newline and indent the printer to the start of the current - /// operation. - virtual void printNewline() = 0; - - /// Increase indentation. - virtual void increaseIndent() = 0; - - /// Decrease indentation. - virtual void decreaseIndent() = 0; - /// Print a block argument in the usual format of: /// %ssaName : type {attr1=42} loc("here") /// where location printing is controlled by the standard internal option. @@ -1654,16 +1656,22 @@ class OpAsmParser : public AsmParser { SmallVectorImpl &result) { size_t operandSize = llvm::range_size(operands); size_t typeSize = llvm::range_size(types); - if (operandSize != typeSize) { + if (typeSize != 0 && operandSize != typeSize) { // If no location was provided, report errors at the beginning of the op. return emitError(loc.isValid() ? loc : getNameLoc()) << "number of operands and types do not match: got " << operandSize << " operands and " << typeSize << " types"; } - for (auto [operand, type] : llvm::zip_equal(operands, types)) - if (resolveOperand(operand, type, result)) - return failure(); + if (typeSize == 0) { + for (auto it : operands) + if (resolveOperand(it, Type(), result)) + return failure(); + } else { + for (auto [operand, type] : llvm::zip_equal(operands, types)) + if (resolveOperand(operand, type, result)) + return failure(); + } return success(); } diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h index 1c2c04e718bf7..11af3b7d4d7b6 100644 --- a/mlir/include/mlir/IR/Operation.h +++ b/mlir/include/mlir/IR/Operation.h @@ -1102,6 +1102,49 @@ inline raw_ostream &operator<<(raw_ostream &os, const Operation &op) { return os; } +/// A wrapper class that allows for printing an operation with a set of flags, +/// useful to act as a "stream modifier" to customize printing an operation +/// with a stream using the operator<< overload, e.g.: +/// llvm::dbgs() << OpWithFlags(op, OpPrintingFlags().skipRegions()); +class OpWithFlags { +public: + OpWithFlags(Operation *op, OpPrintingFlags flags = {}) + : op(op), theFlags(flags) {} + OpPrintingFlags &flags() { return theFlags; } + const OpPrintingFlags &flags() const { return theFlags; } + +private: + Operation *op; + OpPrintingFlags theFlags; + friend raw_ostream &operator<<(raw_ostream &os, const OpWithFlags &op); +}; + +inline raw_ostream &operator<<(raw_ostream &os, + const OpWithFlags &opWithFlags) { + opWithFlags.op->print(os, opWithFlags.flags()); + return os; +} + +/// A wrapper class that allows for printing an operation with a custom +/// AsmState, useful to act as a "stream modifier" to customize printing an +/// operation with a stream using the operator<< overload, e.g.: +/// llvm::dbgs() << OpWithState(op, OpPrintingFlags().skipRegions()); +class OpWithState { +public: + OpWithState(Operation *op, AsmState &state) : op(op), theState(state) {} + +private: + Operation *op; + AsmState &theState; + friend raw_ostream &operator<<(raw_ostream &os, const OpWithState &op); +}; + +inline raw_ostream &operator<<(raw_ostream &os, + const OpWithState &opWithState) { + opWithState.op->print(os, const_cast(opWithState).theState); + return os; +} + } // namespace mlir namespace llvm { diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h index afeb784b85a12..9565eaf4da762 100644 --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -311,14 +311,14 @@ struct OpOrInterfaceRewritePatternBase : public RewritePattern { /// opposed to a raw Operation. template struct OpRewritePattern - : public detail::OpOrInterfaceRewritePatternBase { + : public mlir::detail::OpOrInterfaceRewritePatternBase { /// Patterns must specify the root operation name they match against, and can /// also specify the benefit of the pattern matching and a list of generated /// ops. OpRewritePattern(MLIRContext *context, PatternBenefit benefit = 1, ArrayRef generatedNames = {}) - : detail::OpOrInterfaceRewritePatternBase( + : mlir::detail::OpOrInterfaceRewritePatternBase( SourceOp::getOperationName(), benefit, context, generatedNames) {} }; @@ -327,10 +327,10 @@ struct OpRewritePattern /// of a raw Operation. template struct OpInterfaceRewritePattern - : public detail::OpOrInterfaceRewritePatternBase { + : public mlir::detail::OpOrInterfaceRewritePatternBase { OpInterfaceRewritePattern(MLIRContext *context, PatternBenefit benefit = 1) - : detail::OpOrInterfaceRewritePatternBase( + : mlir::detail::OpOrInterfaceRewritePatternBase( Pattern::MatchInterfaceOpTypeTag(), SourceOp::getInterfaceID(), benefit, context) {} }; diff --git a/mlir/include/mlir/IR/Properties.td b/mlir/include/mlir/IR/Properties.td index a6221f9aaaef9..9be84405c936f 100644 --- a/mlir/include/mlir/IR/Properties.td +++ b/mlir/include/mlir/IR/Properties.td @@ -468,7 +468,7 @@ class ArrayProp, string newSummary = ""> : return $_diag() << "expected array attribute"; for (::mlir::Attribute elemAttr : arrayAttr) { }] # _makePropStorage.ret # [{ - auto elemRes = [&](Attribute propAttr, }] # elem.storageType # [{& propStorage) -> ::mlir::LogicalResult { + auto elemRes = [&](::mlir::Attribute propAttr, }] # elem.storageType # [{& propStorage) -> ::mlir::LogicalResult { }] # !subst("$_attr", "propAttr", !subst("$_storage", "propStorage", elem.convertFromAttribute)) # [{ }(elemAttr, elemVal); @@ -480,7 +480,7 @@ class ArrayProp, string newSummary = ""> : }]; let convertToAttribute = [{ - SmallVector elems; + SmallVector<::mlir::Attribute> elems; for (const auto& elemVal : $_storage) { auto elemAttr = [&](const }] # elem.storageType #[{& propStorage) -> ::mlir::Attribute { }] # !subst("$_storage", "propStorage", elem.convertToAttribute) # [{ @@ -647,7 +647,7 @@ class OptionalProp } ::mlir::Attribute presentAttr = arrayAttr[0]; }] # _makePropStorage.ret # [{ - auto presentRes = [&](Attribute propAttr, }] # p.storageType # [{& propStorage) -> ::mlir::LogicalResult { + auto presentRes = [&](::mlir::Attribute propAttr, }] # p.storageType # [{& propStorage) -> ::mlir::LogicalResult { }] # !subst("$_storage", "propStorage", !subst("$_attr", "propAttr", p.convertFromAttribute)) # [{ }(presentAttr, presentVal); diff --git a/mlir/include/mlir/IR/QuantStorageTypeInterface.h b/mlir/include/mlir/IR/QuantStorageTypeInterface.h new file mode 100644 index 0000000000000..4f5e102feea85 --- /dev/null +++ b/mlir/include/mlir/IR/QuantStorageTypeInterface.h @@ -0,0 +1,20 @@ +//===- QuantStorageTypeInterface.h - Quantzation Interfaces -----*- 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 MLIR_IR_QuantStorageTypeInterface_H +#define MLIR_IR_QuantStorageTypeInterface_H + +#include "mlir/IR/Types.h" + +//===----------------------------------------------------------------------===// +// Tablegen Interface Declarations +//===----------------------------------------------------------------------===// + +#include "mlir/IR/QuantStorageTypeInterface.h.inc" + +#endif // MLIR_IR_QuantStorageTypeInterface_H diff --git a/mlir/include/mlir/IR/QuantStorageTypeInterface.td b/mlir/include/mlir/IR/QuantStorageTypeInterface.td new file mode 100644 index 0000000000000..22dabc58fca54 --- /dev/null +++ b/mlir/include/mlir/IR/QuantStorageTypeInterface.td @@ -0,0 +1,70 @@ +#ifndef MLIR_IR_QUANTSTORAGETYPEINTERFACE +#define MLIR_IR_QUANTSTORAGETYPEINTERFACE + +include "mlir/IR/OpBase.td" + +def QuantStorageTypeInterface : TypeInterface<"QuantStorageTypeInterface"> { + let description = [{ + Interface for types that can be used as storage types in Quant dialect. + This interface provides methods to determine storage characteristics for quantization purposes, + including packing behavior, and alignment requirements. + }]; + let cppNamespace = "::mlir"; + + let methods = [ + InterfaceMethod<[{ + Whether the storage type should default to signed when used in quantization. + Returns true if the type defaults to signed (e.g., si8, i8 or float types), + false if it defaults to unsigned. + }], + "bool", "shouldDefaultToSigned", (ins)>, + + InterfaceMethod<[{ + Get the bit width of this type. + Returns the number of bits used to store values of this type. + }], + "unsigned", "getStorageWidth", (ins)>, + + InterfaceMethod<[{ + Get default minimum value for this type. + }], + "int64_t", "getDefaultMinimum", (ins "bool":$isSigned)>, + + InterfaceMethod<[{ + Get default maximum value for this type. + }], + "int64_t", "getDefaultMaximum", (ins "bool":$isSigned)>, + + InterfaceMethod<[{ + Get the storage type as a string. + }], + "std::string", "getStorageTypeName", (ins "bool":$isSigned)>, + + InterfaceMethod<[{ + Check if the storage type uses packed representation. + Returns true if multiple values are packed into one byte (e.g., sub-byte types), + false if value uses full byte. + }], + "bool", "isPacked", (ins)>, + + InterfaceMethod<[{ + Get the logical bit width per value. + For packed sub-byte types, this may differ from getStorageWidth(). + }], + "unsigned", "getLogicalBitWidth", (ins)>, + + InterfaceMethod<[{ + Get the number of logical elements that fit in one byte. + For packed sub-byte types, this returns how many values can be stored per byte. + }], + "unsigned", "getElementsPerByte", (ins)>, + + InterfaceMethod<[{ + Returns the preferred alignment for this type, in bytes. + }], + "std::optional", "getPreferredAlignmentBytes", (ins)> + ]; + +} + +#endif // MLIR_IR_QUANTSTORAGETYPEINTERFACE diff --git a/mlir/include/mlir/IR/StorageUniquerSupport.h b/mlir/include/mlir/IR/StorageUniquerSupport.h index 2162a74a51580..8959dab047103 100644 --- a/mlir/include/mlir/IR/StorageUniquerSupport.h +++ b/mlir/include/mlir/IR/StorageUniquerSupport.h @@ -200,7 +200,7 @@ class StorageUserBase : public BaseT, public Traits... { // If the construction invariants fail then we return a null attribute. if (failed(ConcreteT::verifyInvariants(emitErrorFn, args...))) return ConcreteT(); - return UniquerT::template get(ctx, args...); + return UniquerT::template get(ctx, std::forward(args)...); } /// Get an instance of the concrete type from a void pointer. diff --git a/mlir/include/mlir/IR/SymbolInterfaces.td b/mlir/include/mlir/IR/SymbolInterfaces.td index a8b04d0453110..f715d82199bd9 100644 --- a/mlir/include/mlir/IR/SymbolInterfaces.td +++ b/mlir/include/mlir/IR/SymbolInterfaces.td @@ -171,11 +171,6 @@ def Symbol : OpInterface<"SymbolOpInterface"> { if (concreteOp.isDeclaration() && concreteOp.isPublic()) return concreteOp.emitOpError("symbol declaration cannot have public " "visibility"); - auto parent = $_op->getParentOp(); - if (parent && !parent->hasTrait() && parent->isRegistered()) { - return concreteOp.emitOpError("symbol's parent must have the SymbolTable " - "trait"); - } return success(); }]; @@ -227,4 +222,6 @@ def SymbolUserOpInterface : OpInterface<"SymbolUserOpInterface"> { // Op defines a symbol table. def SymbolTable : NativeOpTrait<"SymbolTable">; +def SymbolContainer : NativeOpTrait<"SymbolContainer">; + #endif // MLIR_IR_SYMBOLINTERFACES diff --git a/mlir/include/mlir/IR/SymbolTable.h b/mlir/include/mlir/IR/SymbolTable.h index e4622354b8980..007648e0e9b6e 100644 --- a/mlir/include/mlir/IR/SymbolTable.h +++ b/mlir/include/mlir/IR/SymbolTable.h @@ -259,6 +259,13 @@ class SymbolTable { StringAttr newSymbolName, Region *from); + static LogicalResult replaceAllSymbolUses(Operation *oldSymbol, + SymbolRefAttr newSymbolName, + Operation *from); + static LogicalResult replaceAllSymbolUses(Operation *oldSymbol, + SymbolRefAttr newSymbolName, + Region *from); + private: Operation *symbolTableOp; @@ -422,6 +429,7 @@ class SymbolUserMap { /// Replace all of the uses of the given symbol with `newSymbolName`. void replaceAllUsesWith(Operation *symbol, StringAttr newSymbolName); + void replaceAllUsesWith(Operation *symbol, SymbolRefAttr newSymbolName); private: /// A reference to the symbol table used to construct this map. @@ -482,6 +490,40 @@ class SymbolTable : public TraitBase { } }; +template +class SymbolContainer : public TraitBase { +public: + static LogicalResult verifyTrait(Operation *op) { + return mlir::success(); // TODO::implement + } + + /// Look up a symbol with the specified name, returning null if no such + /// name exists. Symbol names never include the @ on them. Note: This + /// performs a linear scan of held symbols. + Operation *lookupSymbol(StringAttr name) { + return mlir::SymbolTable::lookupSymbolIn(this->getOperation(), name); + } + template + T lookupSymbol(StringAttr name) { + return dyn_cast_or_null(lookupSymbol(name)); + } + Operation *lookupSymbol(SymbolRefAttr symbol) { + return mlir::SymbolTable::lookupSymbolIn(this->getOperation(), symbol); + } + template + T lookupSymbol(SymbolRefAttr symbol) { + return dyn_cast_or_null(lookupSymbol(symbol)); + } + + Operation *lookupSymbol(StringRef name) { + return mlir::SymbolTable::lookupSymbolIn(this->getOperation(), name); + } + template + T lookupSymbol(StringRef name) { + return dyn_cast_or_null(lookupSymbol(name)); + } +}; + } // namespace OpTrait //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/IR/Value.h b/mlir/include/mlir/IR/Value.h index 4d6d89fa69a07..c58c5af995e86 100644 --- a/mlir/include/mlir/IR/Value.h +++ b/mlir/include/mlir/IR/Value.h @@ -243,10 +243,7 @@ class Value { detail::ValueImpl *impl; }; -inline raw_ostream &operator<<(raw_ostream &os, Value value) { - value.print(os); - return os; -} +raw_ostream &operator<<(raw_ostream &os, Value value); //===----------------------------------------------------------------------===// // OpOperand diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h index aef7ec622fe4f..f2a7d27f5c78e 100644 --- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h @@ -146,17 +146,17 @@ class EffectInstance { : effect(effect), resource(resource), stage(stage), effectOnFullRegion(effectOnFullRegion) {} template ::value, - bool> = true> + std::enable_if_t::value, + bool> = true> EffectInstance(EffectT *effect, T value, Resource *resource = DefaultResource::get()) : effect(effect), resource(resource), value(value), stage(0), effectOnFullRegion(false) {} template ::value, - bool> = true> + std::enable_if_t::value, + bool> = true> EffectInstance(EffectT *effect, T value, int stage, bool effectOnFullRegion, Resource *resource = DefaultResource::get()) : effect(effect), resource(resource), value(value), stage(stage), @@ -223,6 +223,9 @@ class EffectInstance { if (OpResult result = llvm::dyn_cast_if_present(value)) { return result; } + if (Value result = llvm::dyn_cast_if_present(value)) { + return result; + } return cast_if_present(value); } @@ -264,7 +267,8 @@ class EffectInstance { /// The Symbol, OpOperand, OpResult or BlockArgument that the effect applies /// to. This is optionally null. - PointerUnion value; + PointerUnion + value; /// Additional parameters of the effect instance. An attribute is used for /// type-safe structured storage and context-based uniquing. Concrete effects diff --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h index 16893c6db87b1..c882ab14f78ab 100644 --- a/mlir/include/mlir/Pass/Pass.h +++ b/mlir/include/mlir/Pass/Pass.h @@ -298,6 +298,10 @@ class Pass { /// pass. void copyOptionValuesFrom(const Pass *other); + /// Copy the option values from 'other', which are PassPipeline options. + /// Here we copy only those options that have the same argument name. + void copyOptionValuesFrom(const detail::PassOptions &other); + private: /// Out of line virtual method to ensure vtables and metadata are emitted to a /// single .o file. diff --git a/mlir/include/mlir/Pass/PassOptions.h b/mlir/include/mlir/Pass/PassOptions.h index e1f16c6158ad5..318ea120a0413 100644 --- a/mlir/include/mlir/Pass/PassOptions.h +++ b/mlir/include/mlir/Pass/PassOptions.h @@ -340,6 +340,9 @@ class PassOptions : protected llvm::cl::SubCommand { /// same options as 'this'. void copyOptionValuesFrom(const PassOptions &other); + /// Copy only those options that have the same argument name. + void matchAndCopyOptionValuesFrom(const PassOptions &otherPassOptions); + /// Parse options out as key=value pairs that can then be handed off to the /// `llvm::cl` command line passing infrastructure. Everything is space /// separated. @@ -377,7 +380,7 @@ class PassOptions : protected llvm::cl::SubCommand { /// ListOption someListFlag{*this, "flag-name", llvm::cl::desc("...")}; /// }; template -class PassPipelineOptions : public detail::PassOptions { +class PassPipelineOptions : public virtual detail::PassOptions { public: /// Factory that parses the provided options and returns a unique_ptr to the /// struct. diff --git a/mlir/include/mlir/Support/Timing.h b/mlir/include/mlir/Support/Timing.h index a8a4bfd1c6cf1..3707e9219b6d7 100644 --- a/mlir/include/mlir/Support/Timing.h +++ b/mlir/include/mlir/Support/Timing.h @@ -473,6 +473,11 @@ void registerDefaultTimingManagerCLOptions(); /// 'registerDefaultTimingManagerOptions' to a `DefaultTimingManager`. void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm); +/// Create an output strategy for the specified format, to be passed to +/// DefaultTimingManager::setOutput(). +std::unique_ptr +createOutputStrategy(DefaultTimingManager::OutputFormat fmt, raw_ostream &os); + } // namespace mlir #endif // MLIR_SUPPORT_TIMING_H diff --git a/mlir/include/mlir/Transforms/InliningUtils.h b/mlir/include/mlir/Transforms/InliningUtils.h index ed6413d8cd44c..3fb877c900598 100644 --- a/mlir/include/mlir/Transforms/InliningUtils.h +++ b/mlir/include/mlir/Transforms/InliningUtils.h @@ -172,6 +172,14 @@ class DialectInlinerInterface return result; } + /// Hook to cleanup IR before erase call op + virtual void eraseCall(Operation *call) const; + + /// Hook to get proper place where callable region will be inlined + /// By default returns block of the call operation + virtual std::tuple + getInlineBlockAndPoint(Operation *call) const; + /// Process a set of blocks that have been inlined for a call. This callback /// is invoked before inlined terminator operations have been processed. virtual void processInlinedCallBlocks( diff --git a/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h b/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h index 6d62ae3dd43dc..7d5c1d5cebb26 100644 --- a/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h +++ b/mlir/include/mlir/Transforms/WalkPatternRewriteDriver.h @@ -27,6 +27,8 @@ namespace mlir { /// This is intended as the simplest and most lightweight pattern rewriter in /// cases when a simple walk gets the job done. /// +/// The driver will skip unreachable blocks. +/// /// Note: Does not apply patterns to the given operation itself. void walkAndApplyPatterns(Operation *op, const FrozenRewritePatternSet &patterns, diff --git a/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp b/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp index 6a12fe3acc2c2..e1d7498f7be35 100644 --- a/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp +++ b/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp @@ -295,9 +295,45 @@ RunLivenessAnalysis::RunLivenessAnalysis(Operation *op) { loadBaselineAnalyses(solver); solver.load(symbolTable); - LDBG("Initializing and running solver"); + LLVM_DEBUG({ llvm::dbgs() << "Initializing and running solver\n"; }); (void)solver.initializeAndRun(op); - LDBG("Dumping liveness state for op"); + LLVM_DEBUG({ + llvm::dbgs() << "RunLivenessAnalysis initialized for op: " << op->getName() + << " check on unreachable code now:" + << "\n"; + }); + // The framework doesn't visit operations in dead blocks, so we need to + // explicitly mark them as dead. + op->walk([&](Operation *op) { + if (op->getNumResults() == 0) + return; + for (auto result : llvm::enumerate(op->getResults())) { + if (getLiveness(result.value())) + continue; + LLVM_DEBUG({ + llvm::dbgs() << "Result: " << result.index() << " of " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) + << " has no liveness info (unreachable), mark dead" + << "\n"; + }); + solver.getOrCreateState(result.value()); + } + for (auto ®ion : op->getRegions()) { + for (auto &block : region) { + for (auto blockArg : llvm::enumerate(block.getArguments())) { + if (getLiveness(blockArg.value())) + continue; + LLVM_DEBUG({ + llvm::dbgs() << "Block argument: " << blockArg.index() << " of " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) + << " has no liveness info, mark dead" + << "\n"; + }); + solver.getOrCreateState(blockArg.value()); + } + } + } + }); } const Liveness *RunLivenessAnalysis::getLiveness(Value val) { diff --git a/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp b/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp index e625f626d12fd..5e342fd87773e 100644 --- a/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp +++ b/mlir/lib/Analysis/DataFlow/SparseAnalysis.cpp @@ -19,12 +19,15 @@ #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" #include #include using namespace mlir; using namespace mlir::dataflow; +#define DEBUG_TYPE "dataflow" + //===----------------------------------------------------------------------===// // AbstractSparseLattice //===----------------------------------------------------------------------===// @@ -64,22 +67,56 @@ AbstractSparseForwardDataFlowAnalysis::initialize(Operation *top) { LogicalResult AbstractSparseForwardDataFlowAnalysis::initializeRecursively(Operation *op) { + LLVM_DEBUG({ + llvm::dbgs() << "Initializing recursively for operation: " << op->getName() + << "\n"; + }); + // Initialize the analysis by visiting every owner of an SSA value (all // operations and blocks). - if (failed(visitOperation(op))) + if (failed(visitOperation(op))) { + LLVM_DEBUG({ + llvm::dbgs() << "Failed to visit operation: " << op->getName() << "\n"; + }); return failure(); + } for (Region ®ion : op->getRegions()) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing region with " << region.getBlocks().size() + << " blocks" + << "\n"; + }); for (Block &block : region) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing block with " << block.getNumArguments() + << " arguments" + << "\n"; + }); getOrCreate(getProgramPointBefore(&block)) ->blockContentSubscribe(this); visitBlock(&block); - for (Operation &op : block) - if (failed(initializeRecursively(&op))) + for (Operation &op : block) { + LLVM_DEBUG({ + llvm::dbgs() << "Recursively initializing nested operation: " + << op.getName() << "\n"; + }); + if (failed(initializeRecursively(&op))) { + LLVM_DEBUG({ + llvm::dbgs() << "Failed to initialize nested operation: " + << op.getName() << "\n"; + }); return failure(); + } + } } } + LLVM_DEBUG({ + llvm::dbgs() + << "Successfully completed recursive initialization for operation: " + << op->getName() << "\n"; + }); return success(); } @@ -409,11 +446,29 @@ static MutableArrayRef operandsToOpOperands(OperandRange &operands) { LogicalResult AbstractSparseBackwardDataFlowAnalysis::visitOperation(Operation *op) { + LLVM_DEBUG({ + llvm::dbgs() << "Visiting operation: " << op->getName() << " with " + << op->getNumOperands() << " operands and " + << op->getNumResults() << " results" + << "\n"; + }); + // If we're in a dead block, bail out. if (op->getBlock() != nullptr && - !getOrCreate(getProgramPointBefore(op->getBlock()))->isLive()) + !getOrCreate(getProgramPointBefore(op->getBlock())) + ->isLive()) { + LLVM_DEBUG({ + llvm::dbgs() << "Operation is in dead block, bailing out" + << "\n"; + }); return success(); + } + LLVM_DEBUG({ + llvm::dbgs() << "Creating lattice elements for " << op->getNumOperands() + << " operands and " << op->getNumResults() << " results" + << "\n"; + }); SmallVector operandLattices = getLatticeElements(op->getOperands()); SmallVector resultLattices = @@ -422,11 +477,21 @@ AbstractSparseBackwardDataFlowAnalysis::visitOperation(Operation *op) { // Block arguments of region branch operations flow back into the operands // of the parent op if (auto branch = dyn_cast(op)) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing RegionBranchOpInterface operation" + << "\n"; + }); visitRegionSuccessors(branch, operandLattices); return success(); } if (auto branch = dyn_cast(op)) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing BranchOpInterface operation with " + << op->getNumSuccessors() << " successors" + << "\n"; + }); + // Block arguments of successor blocks flow back into our operands. // We remember all operands not forwarded to any block in a BitVector. @@ -463,6 +528,10 @@ AbstractSparseBackwardDataFlowAnalysis::visitOperation(Operation *op) { // For function calls, connect the arguments of the entry blocks to the // operands of the call op that are forwarded to these arguments. if (auto call = dyn_cast(op)) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing CallOpInterface operation" + << "\n"; + }); Operation *callableOp = call.resolveCallableInTable(&symbolTable); if (auto callable = dyn_cast_or_null(callableOp)) { // Not all operands of a call op forward to arguments. Such operands are @@ -513,6 +582,10 @@ AbstractSparseBackwardDataFlowAnalysis::visitOperation(Operation *op) { // of this op itself and the operands of the terminators of the regions of // this op. if (auto terminator = dyn_cast(op)) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing RegionBranchTerminatorOpInterface operation" + << "\n"; + }); if (auto branch = dyn_cast(op->getParentOp())) { visitRegionSuccessorsFromTerminator(terminator, branch); return success(); @@ -520,12 +593,25 @@ AbstractSparseBackwardDataFlowAnalysis::visitOperation(Operation *op) { } if (op->hasTrait()) { + LLVM_DEBUG({ + llvm::dbgs() << "Processing ReturnLike operation" + << "\n"; + }); // Going backwards, the operands of the return are derived from the // results of all CallOps calling this CallableOp. - if (auto callable = dyn_cast(op->getParentOp())) + if (auto callable = dyn_cast(op->getParentOp())) { + LLVM_DEBUG({ + llvm::dbgs() << "Callable parent found, visiting callable operation" + << "\n"; + }); return visitCallableOperation(op, callable, operandLattices); + } } + LLVM_DEBUG({ + llvm::dbgs() << "Using default visitOperationImpl for operation: " + << op->getName() << "\n"; + }); return visitOperationImpl(op, operandLattices, resultLattices); } diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp index 36a9812bd7972..991c71e3f689a 100644 --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -26,7 +26,8 @@ using namespace mlir; static void -getForwardSliceImpl(Operation *op, SetVector *forwardSlice, +getForwardSliceImpl(Operation *op, DenseSet &visited, + SetVector *forwardSlice, const SliceOptions::TransitiveFilter &filter = nullptr) { if (!op) return; @@ -40,20 +41,41 @@ getForwardSliceImpl(Operation *op, SetVector *forwardSlice, for (Region ®ion : op->getRegions()) for (Block &block : region) for (Operation &blockOp : block) - if (forwardSlice->count(&blockOp) == 0) - getForwardSliceImpl(&blockOp, forwardSlice, filter); - for (Value result : op->getResults()) { - for (Operation *userOp : result.getUsers()) - if (forwardSlice->count(userOp) == 0) - getForwardSliceImpl(userOp, forwardSlice, filter); - } + if (forwardSlice->count(&blockOp) == 0) { + // We don't have to check if the 'blockOp' is already visited because + // there cannot be a traversal path from this nested op to the parent + // and thus a cycle cannot be closed here. We still have to mark it + // as visited to stop before visiting this operation again if it is + // part of a cycle. + visited.insert(&blockOp); + getForwardSliceImpl(&blockOp, visited, forwardSlice, filter); + visited.erase(&blockOp); + } + + for (Value result : op->getResults()) + for (Operation *userOp : result.getUsers()) { + // A cycle can only occur within a basic block (not across regions or + // basic blocks) because the parent region must be a graph region, graph + // regions are restricted to always have 0 or 1 blocks, and there cannot + // be a def-use edge from a nested operation to an operation in an + // ancestor region. Therefore, we don't have to but may use the same + // 'visited' set across regions/blocks as long as we remove operations + // from the set again when the DFS traverses back from the leaf to the + // root. + if (forwardSlice->count(userOp) == 0 && visited.insert(userOp).second) + getForwardSliceImpl(userOp, visited, forwardSlice, filter); + + visited.erase(userOp); + } forwardSlice->insert(op); } void mlir::getForwardSlice(Operation *op, SetVector *forwardSlice, const ForwardSliceOptions &options) { - getForwardSliceImpl(op, forwardSlice, options.filter); + DenseSet visited; + visited.insert(op); + getForwardSliceImpl(op, visited, forwardSlice, options.filter); if (!options.inclusive) { // Don't insert the top level operation, we just queried on it and don't // want it in the results. @@ -69,8 +91,12 @@ void mlir::getForwardSlice(Operation *op, SetVector *forwardSlice, void mlir::getForwardSlice(Value root, SetVector *forwardSlice, const SliceOptions &options) { - for (Operation *user : root.getUsers()) - getForwardSliceImpl(user, forwardSlice, options.filter); + DenseSet visited; + for (Operation *user : root.getUsers()) { + visited.insert(user); + getForwardSliceImpl(user, visited, forwardSlice, options.filter); + visited.erase(user); + } // Reverse to get back the actual topological order. // std::reverse does not work out of the box on SetVector and I want an @@ -80,6 +106,7 @@ void mlir::getForwardSlice(Value root, SetVector *forwardSlice, } static LogicalResult getBackwardSliceImpl(Operation *op, + DenseSet &visited, SetVector *backwardSlice, const BackwardSliceOptions &options) { if (!op || op->hasTrait()) @@ -93,8 +120,12 @@ static LogicalResult getBackwardSliceImpl(Operation *op, auto processValue = [&](Value value) { if (auto *definingOp = value.getDefiningOp()) { - if (backwardSlice->count(definingOp) == 0) - return getBackwardSliceImpl(definingOp, backwardSlice, options); + if (backwardSlice->count(definingOp) == 0 && + visited.insert(definingOp).second) + return getBackwardSliceImpl(definingOp, visited, backwardSlice, + options); + + visited.erase(definingOp); } else if (auto blockArg = dyn_cast(value)) { if (options.omitBlockArguments) return success(); @@ -107,7 +138,8 @@ static LogicalResult getBackwardSliceImpl(Operation *op, if (parentOp && backwardSlice->count(parentOp) == 0) { if (parentOp->getNumRegions() == 1 && llvm::hasSingleElement(parentOp->getRegion(0).getBlocks())) { - return getBackwardSliceImpl(parentOp, backwardSlice, options); + return getBackwardSliceImpl(parentOp, visited, backwardSlice, + options); } } } else { @@ -145,7 +177,10 @@ static LogicalResult getBackwardSliceImpl(Operation *op, LogicalResult mlir::getBackwardSlice(Operation *op, SetVector *backwardSlice, const BackwardSliceOptions &options) { - LogicalResult result = getBackwardSliceImpl(op, backwardSlice, options); + DenseSet visited; + visited.insert(op); + LogicalResult result = + getBackwardSliceImpl(op, visited, backwardSlice, options); if (!options.inclusive) { // Don't insert the top level operation, we just queried on it and don't diff --git a/mlir/lib/AsmParser/DialectSymbolParser.cpp b/mlir/lib/AsmParser/DialectSymbolParser.cpp index 9f4a87a6a02de..416d8eb5f40e0 100644 --- a/mlir/lib/AsmParser/DialectSymbolParser.cpp +++ b/mlir/lib/AsmParser/DialectSymbolParser.cpp @@ -89,6 +89,7 @@ ParseResult Parser::parseDialectSymbolBody(StringRef &body, nestedPunctuation.pop_back(); return success(); }; + const char *curBufferEnd = state.lex.getBufferEnd(); do { // Handle code completions, which may appear in the middle of the symbol // body. @@ -98,6 +99,12 @@ ParseResult Parser::parseDialectSymbolBody(StringRef &body, break; } + if (curBufferEnd == curPtr) { + if (!nestedPunctuation.empty()) + return emitPunctError(); + return emitError("unexpected nul or EOF in pretty dialect name"); + } + char c = *curPtr++; switch (c) { case '\0': @@ -238,6 +245,15 @@ static Symbol parseExtendedSymbol(Parser &p, AsmParserState *asmState, return nullptr; } + if constexpr (std::is_same_v) { + auto &cache = p.getState().symbols.attributesCache; + auto cacheIt = cache.find(symbolData); + // Skip cached attribute if it has type. + if (cacheIt != cache.end() && !p.getToken().is(Token::colon)) + return cacheIt->second; + + return cache[symbolData] = createSymbol(dialectName, symbolData, loc); + } return createSymbol(dialectName, symbolData, loc); } @@ -330,6 +346,7 @@ Type Parser::parseExtendedType() { template static T parseSymbol(StringRef inputStr, MLIRContext *context, size_t *numReadOut, bool isKnownNullTerminated, + llvm::StringMap *attributesCache, ParserFn &&parserFn) { // Set the buffer name to the string being parsed, so that it appears in error // diagnostics. @@ -341,6 +358,9 @@ static T parseSymbol(StringRef inputStr, MLIRContext *context, SourceMgr sourceMgr; sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc()); SymbolState aliasState; + if (attributesCache) + aliasState.attributesCache = *attributesCache; + ParserConfig config(context); ParserState state(sourceMgr, config, aliasState, /*asmState=*/nullptr, /*codeCompleteContext=*/nullptr); @@ -351,6 +371,11 @@ static T parseSymbol(StringRef inputStr, MLIRContext *context, if (!symbol) return T(); + if constexpr (std::is_same_v) { + if (attributesCache) + *attributesCache = state.symbols.attributesCache; + } + // Provide the number of bytes that were read. Token endTok = parser.getToken(); size_t numRead = @@ -367,13 +392,15 @@ static T parseSymbol(StringRef inputStr, MLIRContext *context, Attribute mlir::parseAttribute(StringRef attrStr, MLIRContext *context, Type type, size_t *numRead, - bool isKnownNullTerminated) { + bool isKnownNullTerminated, + llvm::StringMap *attributesCache) { return parseSymbol( - attrStr, context, numRead, isKnownNullTerminated, + attrStr, context, numRead, isKnownNullTerminated, attributesCache, [type](Parser &parser) { return parser.parseAttribute(type); }); } Type mlir::parseType(StringRef typeStr, MLIRContext *context, size_t *numRead, bool isKnownNullTerminated) { return parseSymbol(typeStr, context, numRead, isKnownNullTerminated, + /*attributesCache=*/nullptr, [](Parser &parser) { return parser.parseType(); }); } diff --git a/mlir/lib/AsmParser/Lexer.cpp b/mlir/lib/AsmParser/Lexer.cpp index 751bd63e537f8..8f53529823e23 100644 --- a/mlir/lib/AsmParser/Lexer.cpp +++ b/mlir/lib/AsmParser/Lexer.cpp @@ -37,6 +37,18 @@ Lexer::Lexer(const llvm::SourceMgr &sourceMgr, MLIRContext *context, AsmParserCodeCompleteContext *codeCompleteContext) : sourceMgr(sourceMgr), context(context), codeCompleteLoc(nullptr) { auto bufferID = sourceMgr.getMainFileID(); + + // Check to see if the main buffer contains the last buffer, and if so the + // last buffer should be used as main file for parsing. + if (sourceMgr.getNumBuffers() > 1) { + unsigned lastFileID = sourceMgr.getNumBuffers(); + const llvm::MemoryBuffer *main = sourceMgr.getMemoryBuffer(bufferID); + const llvm::MemoryBuffer *last = sourceMgr.getMemoryBuffer(lastFileID); + if (main->getBufferStart() <= last->getBufferStart() && + main->getBufferEnd() >= last->getBufferEnd()) { + bufferID = lastFileID; + } + } curBuffer = sourceMgr.getMemoryBuffer(bufferID)->getBuffer(); curPtr = curBuffer.begin(); @@ -71,6 +83,7 @@ Token Lexer::emitError(const char *loc, const Twine &message) { } Token Lexer::lexToken() { + const char *curBufferEnd = curBuffer.end(); while (true) { const char *tokStart = curPtr; @@ -78,6 +91,9 @@ Token Lexer::lexToken() { if (tokStart == codeCompleteLoc) return formToken(Token::code_complete, tokStart); + if (tokStart == curBufferEnd) + return formToken(Token::eof, tokStart); + // Lex the next token. switch (*curPtr++) { default: @@ -102,7 +118,7 @@ Token Lexer::lexToken() { case 0: // This may either be a nul character in the source file or may be the EOF // marker that llvm::MemoryBuffer guarantees will be there. - if (curPtr - 1 == curBuffer.end()) + if (curPtr - 1 == curBufferEnd) return formToken(Token::eof, tokStart); continue; @@ -259,7 +275,11 @@ void Lexer::skipComment() { assert(*curPtr == '/'); ++curPtr; + const char *curBufferEnd = curBuffer.end(); while (true) { + if (curPtr == curBufferEnd) + return; + switch (*curPtr++) { case '\n': case '\r': @@ -267,7 +287,7 @@ void Lexer::skipComment() { return; case 0: // If this is the end of the buffer, end the comment. - if (curPtr - 1 == curBuffer.end()) { + if (curPtr - 1 == curBufferEnd) { --curPtr; return; } @@ -405,6 +425,7 @@ Token Lexer::lexPrefixedIdentifier(const char *tokStart) { Token Lexer::lexString(const char *tokStart) { assert(curPtr[-1] == '"'); + const char *curBufferEnd = curBuffer.end(); while (true) { // Check to see if there is a code completion location within the string. In // these cases we generate a completion location and place the currently @@ -419,7 +440,7 @@ Token Lexer::lexString(const char *tokStart) { case 0: // If this is a random nul character in the middle of a string, just // include it. If it is the end of file, then it is an error. - if (curPtr - 1 != curBuffer.end()) + if (curPtr - 1 != curBufferEnd) continue; [[fallthrough]]; case '\n': diff --git a/mlir/lib/AsmParser/Lexer.h b/mlir/lib/AsmParser/Lexer.h index 4085a9b73854b..670444eb1f5b4 100644 --- a/mlir/lib/AsmParser/Lexer.h +++ b/mlir/lib/AsmParser/Lexer.h @@ -40,6 +40,9 @@ class Lexer { /// Returns the start of the buffer. const char *getBufferBegin() { return curBuffer.data(); } + /// Returns the end of the buffer. + const char *getBufferEnd() { return curBuffer.end(); } + /// Return the code completion location of the lexer, or nullptr if there is /// none. const char *getCodeCompleteLoc() const { return codeCompleteLoc; } diff --git a/mlir/lib/AsmParser/Parser.cpp b/mlir/lib/AsmParser/Parser.cpp index 756d3d01a4534..b444181c30251 100644 --- a/mlir/lib/AsmParser/Parser.cpp +++ b/mlir/lib/AsmParser/Parser.cpp @@ -1093,16 +1093,24 @@ Value OperationParser::resolveSSAUse(UnresolvedOperand useInfo, Type type) { // If we have already seen a value of this name, return it. if (useInfo.number < entries.size() && entries[useInfo.number].value) { Value result = entries[useInfo.number].value; + // Check that the type matches the other uses. - if (result.getType() == type) - return maybeRecordUse(result); - - emitError(useInfo.location, "use of value '") - .append(useInfo.name, - "' expects different type than prior uses: ", type, " vs ", - result.getType()) - .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc)) - .append("prior use here"); + if (type && result.getType() != type) { + emitError(useInfo.location, "use of value '") + .append(useInfo.name, + "' expects different type than prior uses: ", type, " vs ", + result.getType()) + .attachNote(getEncodedSourceLocation(entries[useInfo.number].loc)) + .append("prior use here"); + return nullptr; + } + + return maybeRecordUse(result); + } + + if (!type) { + emitError(useInfo.location, "forward reference of value '") + .append(useInfo.name, "' requires explicit type specification"); return nullptr; } diff --git a/mlir/lib/AsmParser/ParserState.h b/mlir/lib/AsmParser/ParserState.h index 159058a18fa4e..aa53032107cbf 100644 --- a/mlir/lib/AsmParser/ParserState.h +++ b/mlir/lib/AsmParser/ParserState.h @@ -40,6 +40,9 @@ struct SymbolState { /// A map from unique integer identifier to DistinctAttr. DenseMap distinctAttributes; + + /// A map from unique string identifier to Attribute. + llvm::StringMap attributesCache; }; //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp index 44458d010c6c8..0f97443433774 100644 --- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp +++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp @@ -895,6 +895,10 @@ class AttrTypeReader { SmallVector attributes; SmallVector types; + /// The map of cached attributes, used to avoid re-parsing the same + /// attribute multiple times. + llvm::StringMap attributesCache; + /// A location used for error emission. Location fileLoc; @@ -1235,7 +1239,7 @@ LogicalResult AttrTypeReader::parseAsmEntry(T &result, EncodingReader &reader, ::parseType(asmStr, context, &numRead, /*isKnownNullTerminated=*/true); else result = ::parseAttribute(asmStr, context, Type(), &numRead, - /*isKnownNullTerminated=*/true); + /*isKnownNullTerminated=*/true, &attributesCache); if (!result) return failure(); diff --git a/mlir/lib/Conversion/SCFToControlFlow/SCFToControlFlow.cpp b/mlir/lib/Conversion/SCFToControlFlow/SCFToControlFlow.cpp index 0df91a243d07a..523dc463a0da1 100644 --- a/mlir/lib/Conversion/SCFToControlFlow/SCFToControlFlow.cpp +++ b/mlir/lib/Conversion/SCFToControlFlow/SCFToControlFlow.cpp @@ -582,6 +582,7 @@ LogicalResult WhileLowering::matchAndRewrite(WhileOp whileOp, // block. This should be reconsidered if we allow break/continue in SCF. rewriter.setInsertionPointToEnd(before); auto condOp = cast(before->getTerminator()); + SmallVector args = llvm::to_vector(condOp.getArgs()); rewriter.replaceOpWithNewOp(condOp, condOp.getCondition(), after, condOp.getArgs(), continuation, ValueRange()); @@ -593,7 +594,7 @@ LogicalResult WhileLowering::matchAndRewrite(WhileOp whileOp, // Replace the op with values "yielded" from the "before" region, which are // visible by dominance. - rewriter.replaceOp(whileOp, condOp.getArgs()); + rewriter.replaceOp(whileOp, args); return success(); } diff --git a/mlir/lib/Dialect/Arith/IR/CMakeLists.txt b/mlir/lib/Dialect/Arith/IR/CMakeLists.txt index 4beb99ccfdfba..ffcdf46d7a801 100644 --- a/mlir/lib/Dialect/Arith/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Arith/IR/CMakeLists.txt @@ -22,6 +22,7 @@ add_mlir_dialect_library(MLIRArithDialect MLIRArithOpsInterfacesIncGen LINK_LIBS PUBLIC + MLIRTransformUtils MLIRCastInterfaces MLIRDialect MLIRInferIntRangeCommon diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp index 8f17a82fabe03..3eef4d673d771 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp @@ -341,11 +341,21 @@ bool OpFilter::isOpAllowed(Operation *op) const { namespace { /// Default function arg type converter: Use a fully dynamic layout map. -BaseMemRefType -defaultFunctionArgTypeConverter(TensorType type, Attribute memorySpace, +BufferLikeType +defaultFunctionArgTypeConverter(TensorLikeType type, Attribute memorySpace, func::FuncOp funcOp, const BufferizationOptions &options) { - return getMemRefTypeWithFullyDynamicLayout(type, memorySpace); + if (auto tensorType = mlir::dyn_cast(type)) { + return cast( + getMemRefTypeWithFullyDynamicLayout(tensorType, memorySpace)); + } + + // If not builtin, fallback to TensorLikeType::getBufferType() + auto bufferType = + type.getBufferType(options, [&]() { return funcOp->emitError(); }); + assert(succeeded(bufferType) && + "a valid buffer is always expected at function boundary"); + return *bufferType; } /// Default unknown type converter: Use a fully dynamic layout map. BaseMemRefType @@ -388,14 +398,25 @@ BufferizationOptions::dynCastBufferizableOp(Value value) const { void BufferizationOptions::setFunctionBoundaryTypeConversion( LayoutMapOption layoutMapOption) { - functionArgTypeConverterFn = [=](TensorType tensorType, Attribute memorySpace, + functionArgTypeConverterFn = [=](TensorLikeType type, Attribute memorySpace, func::FuncOp funcOp, const BufferizationOptions &options) { - if (layoutMapOption == LayoutMapOption::IdentityLayoutMap) - return bufferization::getMemRefTypeWithStaticIdentityLayout(tensorType, - memorySpace); - return bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType, - memorySpace); + if (auto tensorType = mlir::dyn_cast(type)) { + if (layoutMapOption == LayoutMapOption::IdentityLayoutMap) + return cast( + bufferization::getMemRefTypeWithStaticIdentityLayout(tensorType, + memorySpace)); + return cast( + bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType, + memorySpace)); + } + + // If not builtin, fallback to TensorLikeType::getBufferType() + auto bufferType = + type.getBufferType(options, [&]() { return funcOp->emitError(); }); + assert(succeeded(bufferType) && + "a valid buffer is always expected at function boundary"); + return *bufferType; }; inferFunctionResultLayout = layoutMapOption == LayoutMapOption::InferLayoutMap; @@ -662,16 +683,6 @@ bool AnalysisState::hasUndefinedContents(OpOperand *opOperand) const { return false; } -// bufferization.to_buffer is not allowed to change the rank. -static void ensureToBufferOpIsValid(Value tensor, Type memrefType) { -#ifndef NDEBUG - auto rankedTensorType = llvm::dyn_cast(tensor.getType()); - assert((!rankedTensorType || llvm::cast(memrefType).getRank() == - rankedTensorType.getRank()) && - "to_buffer would be invalid: mismatching ranks"); -#endif -} - FailureOr bufferization::getBuffer(RewriterBase &rewriter, Value value, const BufferizationOptions &options, const BufferizationState &state) { @@ -690,7 +701,7 @@ FailureOr bufferization::getBuffer(RewriterBase &rewriter, Value value, FailureOr bufferType = getBufferType(value, options, state); if (failed(bufferType)) return failure(); - ensureToBufferOpIsValid(value, *bufferType); + return rewriter .create(value.getLoc(), *bufferType, value) .getResult(); diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationDialect.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationDialect.cpp index 6c08cdfb669f3..71d5fcb233f41 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizationDialect.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationDialect.cpp @@ -73,9 +73,6 @@ struct BuiltinTensorExternalModel mlir::LogicalResult verifyCompatibleBufferType( mlir::Type tensor, BufferLikeType bufferType, llvm::function_ref emitError) const { - assert(isa(tensor) && "expected tensor type"); - assert(isa(bufferType) && "expected memref type"); - auto tensorType = cast(tensor); auto memrefType = cast(bufferType); diff --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp index 246555dc8c699..37509e561f401 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp @@ -404,7 +404,7 @@ bufferization::bufferizeBlockSignature(Block *block, RewriterBase &rewriter, // Compute the new signature. SmallVector newTypes; for (BlockArgument &bbArg : block->getArguments()) { - auto tensorType = dyn_cast(bbArg.getType()); + auto tensorType = dyn_cast(bbArg.getType()); if (!tensorType) { newTypes.push_back(bbArg.getType()); continue; diff --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp index 2a98203da9d7d..4c29d657d443b 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp @@ -49,29 +49,47 @@ void FuncAnalysisState::startFunctionAnalysis(FuncOp funcOp) { #endif // NDEBUG } +// Note: this is a local adaptor to unify TensorType and TensorLikeType code +// paths that both work with BufferizationOptions. +static mlir::Attribute +getDefaultMemorySpace(const BufferizationOptions &options, + TensorLikeType type) { + if (auto tensorType = dyn_cast(type)) { + return *options.defaultMemorySpaceFn(tensorType); + } + return nullptr; +} + /// Return the index-th bufferized function argument type. This assumes that the /// specified argument is a tensor. If the tensor is ranked, a layout map may be /// specified by the user (as per `options.functionArgTypeConverterFn`). -static BaseMemRefType +static BufferLikeType getBufferizedFunctionArgType(FuncOp funcOp, int64_t index, const BufferizationOptions &options) { - auto tensorType = - dyn_cast(funcOp.getFunctionType().getInput(index)); - assert(tensorType && "expected TensorType"); - - BaseMemRefType memrefType = options.functionArgTypeConverterFn( - tensorType, *options.defaultMemorySpaceFn(tensorType), funcOp, options); - - auto layoutAttr = funcOp.getArgAttrOfType( - index, BufferizationDialect::kBufferLayoutAttrName); - if (!layoutAttr) - return memrefType; - - auto rankedMemrefType = dyn_cast(memrefType); - assert(rankedMemrefType && "buffer layout not supported on unranked tensors"); - return MemRefType::get(rankedMemrefType.getShape(), - rankedMemrefType.getElementType(), layoutAttr, - rankedMemrefType.getMemorySpace()); + auto type = + dyn_cast(funcOp.getFunctionType().getInput(index)); + assert(type && "expected TensorLikeType"); + + // Note: For builtin tensors there is additional logic related to layout. + if (auto tensorType = dyn_cast(type)) { + BufferLikeType memrefType = options.functionArgTypeConverterFn( + type, *options.defaultMemorySpaceFn(tensorType), funcOp, options); + + auto layoutAttr = funcOp.getArgAttrOfType( + index, BufferizationDialect::kBufferLayoutAttrName); + if (!layoutAttr) + return memrefType; + + auto rankedMemrefType = dyn_cast(memrefType); + assert(rankedMemrefType && + "buffer layout not supported on unranked tensors"); + return cast(MemRefType::get( + rankedMemrefType.getShape(), rankedMemrefType.getElementType(), + layoutAttr, rankedMemrefType.getMemorySpace())); + } + + return options.functionArgTypeConverterFn(type, /*memSpace=*/nullptr, funcOp, + options); } /// Return the FuncOp called by `callOp`. @@ -227,13 +245,13 @@ struct CallOpInterface FunctionType funcType = funcOp.getFunctionType(); Type resultType = funcType.getResult(cast(value).getResultNumber()); - if (auto bufferizedType = dyn_cast(resultType)) - return cast(bufferizedType); + if (auto bufferizedType = dyn_cast(resultType)) + return bufferizedType; // Otherwise, call the type converter to compute the bufferized type. - auto tensorType = cast(resultType); + auto tensorType = cast(resultType); return cast(options.functionArgTypeConverterFn( - tensorType, *options.defaultMemorySpaceFn(tensorType), funcOp, + tensorType, getDefaultMemorySpace(options, tensorType), funcOp, options)); } @@ -248,7 +266,7 @@ struct CallOpInterface SmallVector resultTypes; for (Value result : callOp.getResults()) { Type returnType = result.getType(); - if (!isa(returnType)) { + if (!isa(returnType)) { // Non-tensor values are returned. resultTypes.push_back(returnType); continue; @@ -272,7 +290,7 @@ struct CallOpInterface for (OpOperand &opOperand : callOp->getOpOperands()) { // Non-tensor operands are just copied. - if (!isa(opOperand.get().getType())) { + if (!isa(opOperand.get().getType())) { newOperands.push_back(opOperand.get()); continue; } @@ -285,8 +303,8 @@ struct CallOpInterface Value buffer = *maybeBuffer; // Caller / callee type mismatch is handled with castOrReallocMemRefValue. - auto memRefType = funcType.getInput(opOperand.getOperandNumber()); - if (!isa(memRefType)) { + auto bufferType = funcType.getInput(opOperand.getOperandNumber()); + if (!isa(bufferType)) { // The called function was not bufferized yet. This can happen when // there cycles in the function call graph. Compute the bufferized // result type. @@ -296,7 +314,7 @@ struct CallOpInterface state); if (failed(maybeBufferType)) return failure(); - memRefType = *maybeBufferType; + bufferType = *maybeBufferType; } // Since we don't yet have a clear layout story, to_buffer may @@ -305,8 +323,8 @@ struct CallOpInterface // that will either canonicalize away or fail compilation until we can do // something better. Insert a reallocation + copy if it cannot be // statically guaranteed that a direct cast would be valid. - if (buffer.getType() != memRefType) { - auto memrefDstType = dyn_cast(memRefType); + if (buffer.getType() != bufferType) { + auto memrefDstType = dyn_cast(bufferType); assert(memrefDstType && "buffer layout not supported on unranked tensors"); FailureOr replacement = bufferization::castOrReallocMemRefValue( @@ -369,7 +387,7 @@ struct FuncOpInterface static bool supportsUnstructuredControlFlow() { return true; } bool hasTensorSemantics(Operation *op) const { - auto isaTensor = llvm::IsaPred; + auto isaTensor = llvm::IsaPred; // A function has tensor semantics if it has tensor arguments/results. auto funcOp = cast(op); @@ -405,8 +423,8 @@ struct FuncOpInterface // Function arguments are special. if (bbArg.getOwner() == &funcOp.getBody().front()) - return cast( - getBufferizedFunctionArgType(funcOp, bbArg.getArgNumber(), options)); + return getBufferizedFunctionArgType(funcOp, bbArg.getArgNumber(), + options); return OpWithUnstructuredControlFlowBufferizableOpInterfaceExternalModel:: getBufferType(op, value, options, state, invocationStack); @@ -429,7 +447,7 @@ struct FuncOpInterface SmallVector argTypes; for (const auto &it : llvm::enumerate(funcType.getInputs())) { Type argType = it.value(); - if (isa(argType)) { + if (isa(argType)) { argTypes.push_back( getBufferizedFunctionArgType(funcOp, it.index(), options)); continue; @@ -440,9 +458,9 @@ struct FuncOpInterface // Compute the result types. SmallVector retTypes; for (Type resultType : funcType.getResults()) { - if (auto tensorType = dyn_cast(resultType)) { - BaseMemRefType resultType = options.functionArgTypeConverterFn( - tensorType, *options.defaultMemorySpaceFn(tensorType), funcOp, + if (auto tensorType = dyn_cast(resultType)) { + BufferLikeType resultType = options.functionArgTypeConverterFn( + tensorType, getDefaultMemorySpace(options, tensorType), funcOp, options); retTypes.push_back(resultType); continue; @@ -472,7 +490,7 @@ struct FuncOpInterface SmallVector returnValues; for (auto [returnVal, bufferizedType] : llvm::zip_equal(returnOp->getOperands(), retTypes)) { - auto tensorType = dyn_cast(returnVal.getType()); + auto tensorType = dyn_cast(returnVal.getType()); rewriter.setInsertionPoint(returnOp); // If not a tensor type just forward it. diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt index d987b72e98354..c58ff5673bf08 100644 --- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt +++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt @@ -28,6 +28,7 @@ add_mlir_dialect_library(MLIRLLVMDialect Core LINK_LIBS PUBLIC + MLIRTransformUtils MLIRCallInterfaces MLIRControlFlowInterfaces MLIRDataLayoutInterfaces diff --git a/mlir/lib/Dialect/Quant/IR/QuantDialectBytecode.cpp b/mlir/lib/Dialect/Quant/IR/QuantDialectBytecode.cpp index 1b3cc5a43f460..870f13d4fb8c2 100644 --- a/mlir/lib/Dialect/Quant/IR/QuantDialectBytecode.cpp +++ b/mlir/lib/Dialect/Quant/IR/QuantDialectBytecode.cpp @@ -30,6 +30,29 @@ static LogicalResult readDoubleAPFloat(DialectBytecodeReader &reader, return success(); } +static LogicalResult readOptionalSignedVarInt(DialectBytecodeReader &reader, + std::optional &val) { + bool hasValue; + if (failed(reader.readBool(hasValue))) + return failure(); + if (hasValue) { + int64_t v; + if (failed(reader.readSignedVarInt(v))) + return failure(); + val = v; + } else { + val = std::nullopt; + } + return success(); +} + +static void writeOptionalSignedVarInt(DialectBytecodeWriter &writer, + std::optional val) { + writer.writeOwnedBool(val.has_value()); + if (val.has_value()) + writer.writeSignedVarInt(*val); +} + #include "mlir/Dialect/Quant/IR/QuantDialectBytecode.cpp.inc" /// This class implements the bytecode interface for the Quant dialect. diff --git a/mlir/lib/Dialect/Quant/IR/QuantOps.cpp b/mlir/lib/Dialect/Quant/IR/QuantOps.cpp index e23a0d6aba825..1754799053c40 100644 --- a/mlir/lib/Dialect/Quant/IR/QuantOps.cpp +++ b/mlir/lib/Dialect/Quant/IR/QuantOps.cpp @@ -191,7 +191,8 @@ LogicalResult verifyQuantizationOp(Operation *op, QuantizedType quantizedType, void QuantDialect::initialize() { addTypes(); + UniformQuantizedPerAxisType, UniformQuantizedSubChannelType, + QuantileType>(); addOperations< #define GET_OP_LIST #include "mlir/Dialect/Quant/IR/QuantOps.cpp.inc" diff --git a/mlir/lib/Dialect/Quant/IR/QuantTypes.cpp b/mlir/lib/Dialect/Quant/IR/QuantTypes.cpp index 8122c4db684e5..ef6cb796c2121 100644 --- a/mlir/lib/Dialect/Quant/IR/QuantTypes.cpp +++ b/mlir/lib/Dialect/Quant/IR/QuantTypes.cpp @@ -9,6 +9,9 @@ #include "mlir/Dialect/Quant/IR/QuantTypes.h" #include "TypeDetail.h" #include "mlir/Dialect/Quant/IR/Quant.h" +#include "mlir/IR/DialectImplementation.h" +#include "mlir/IR/OpImplementation.h" +#include "mlir/IR/QuantStorageTypeInterface.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/MLIRContext.h" @@ -22,7 +25,8 @@ namespace { // Return the minimum scale representable in a given float type double getMinScale(Type expressedType) { auto floatType = cast(expressedType); - return APFloat::getSmallest(floatType.getFloatSemantics()).convertToDouble(); + return APFloat::getLargest(floatType.getFloatSemantics(), /*Negative=*/true) + .convertToDouble(); } // Return the maximum scale representable in a given float type @@ -38,7 +42,8 @@ unsigned QuantizedType::getFlags() const { } bool QuantizedType::classof(Type type) { - return llvm::isa(type.getDialect()); + return llvm::isa(type.getDialect()) && + !llvm::isa(type); } LogicalResult @@ -46,32 +51,28 @@ QuantizedType::verifyInvariants(function_ref emitError, unsigned flags, Type storageType, Type expressedType, int64_t storageTypeMin, int64_t storageTypeMax) { - // Verify that the storage type is integral. - // This restriction may be lifted at some point in favor of using bf16 - // or f16 as exact representations on hardware where that is advantageous. - auto intStorageType = llvm::dyn_cast(storageType); - if (!intStorageType) - return emitError() << "storage type must be integral"; - unsigned integralWidth = intStorageType.getWidth(); - - // Verify storage width. - if (integralWidth == 0 || integralWidth > MaxStorageBits) - return emitError() << "illegal storage type size: " << integralWidth; - - // Verify storageTypeMin and storageTypeMax. - bool isSigned = - (flags & QuantizationFlags::Signed) == QuantizationFlags::Signed; - int64_t defaultIntegerMin = - getDefaultMinimumForInteger(isSigned, integralWidth); - int64_t defaultIntegerMax = - getDefaultMaximumForInteger(isSigned, integralWidth); - if (storageTypeMax - storageTypeMin <= 0 || - storageTypeMin < defaultIntegerMin || - storageTypeMax > defaultIntegerMax) { - return emitError() << "illegal storage min and storage max: (" - << storageTypeMin << ":" << storageTypeMax << ")"; + if (auto quantStorageTypeInterface = + llvm::dyn_cast(storageType)) { + unsigned integralWidth = quantStorageTypeInterface.getStorageWidth(); + + // Verify storage width. + if (integralWidth == 0 || integralWidth > MaxStorageBits) + return emitError() << "illegal storage type size: " << integralWidth; + + bool isSigned = flags & QuantizationFlags::Signed; + int64_t defaultMin = quantStorageTypeInterface.getDefaultMinimum(isSigned); + int64_t defaultMax = quantStorageTypeInterface.getDefaultMaximum(isSigned); + + if (storageTypeMax - storageTypeMin <= 0 || storageTypeMin < defaultMin || + storageTypeMax > defaultMax) { + return emitError() << "illegal storage min and storage max: (" + << storageTypeMin << ":" << storageTypeMax << ")"; + } + + return success(); } - return success(); + + return emitError() << "storage type must implement QuantStorageTypeInterface"; } Type QuantizedType::getStorageType() const { @@ -87,20 +88,22 @@ int64_t QuantizedType::getStorageTypeMax() const { } bool QuantizedType::hasStorageTypeBounds() const { - unsigned int integralWidth = getStorageTypeIntegralWidth(); - bool isSignedInteger = isSigned(); - int64_t defaultIntegerMin = - getDefaultMinimumForInteger(isSignedInteger, integralWidth); - int64_t defaultIntegerMax = - getDefaultMaximumForInteger(isSignedInteger, integralWidth); - return defaultIntegerMin != getStorageTypeMin() || - defaultIntegerMax != getStorageTypeMax(); + Type storageType = static_cast(impl)->storageType; + auto quantStorageTypeInterface = + llvm::dyn_cast(storageType); + + int64_t defaultMin = quantStorageTypeInterface.getDefaultMinimum(isSigned()); + int64_t defaultMax = quantStorageTypeInterface.getDefaultMaximum(isSigned()); + + return defaultMin != getStorageTypeMin() || defaultMax != getStorageTypeMax(); } unsigned QuantizedType::getStorageTypeIntegralWidth() const { - // NOTE: If ever supporting non-integral storage types, some other scheme - // for determining the width will be needed. - return static_cast(impl)->storageType.getIntOrFloatBitWidth(); + Type storageType = static_cast(impl)->storageType; + auto quantStorageTypeInterface = + llvm::dyn_cast(storageType); + + return quantStorageTypeInterface.getStorageWidth(); } Type QuantizedType::getExpressedType() const { @@ -319,13 +322,17 @@ LogicalResult UniformQuantizedType::verifyInvariants( // Verify scale. double minScale = getMinScale(expressedType); double maxScale = getMaxScale(expressedType); - if (scale < minScale || scale > maxScale) + if (scale < minScale || scale > maxScale || std::isnan(scale)) return emitError() << "scale out of expressed type range [" << minScale << ", " << maxScale << "]"; return success(); } +bool UniformQuantizedType::classof(mlir::Type type) { + return type.getTypeID() == mlir::TypeID::get(); +} + double UniformQuantizedType::getScale() const { return getImpl()->scale; } int64_t UniformQuantizedType::getZeroPoint() const { @@ -383,7 +390,7 @@ LogicalResult UniformQuantizedPerAxisType::verifyInvariants( double minScale = getMinScale(expressedType); double maxScale = getMaxScale(expressedType); for (double scale : scales) { - if (scale < minScale || scale > maxScale) + if (scale < minScale || scale > maxScale || std::isnan(scale)) return emitError() << "scale out of expressed type range [" << minScale << ", " << maxScale << "]"; } @@ -395,6 +402,10 @@ LogicalResult UniformQuantizedPerAxisType::verifyInvariants( return success(); } +bool UniformQuantizedPerAxisType::classof(mlir::Type type) { + return type.getTypeID() == mlir::TypeID::get(); +} + ArrayRef UniformQuantizedPerAxisType::getScales() const { return getImpl()->getScales(); } @@ -553,3 +564,140 @@ LogicalResult CalibratedQuantizedType::verifyInvariants( double CalibratedQuantizedType::getMin() const { return getImpl()->min; } double CalibratedQuantizedType::getMax() const { return getImpl()->max; } + +QuantileType QuantileType::get(mlir::MLIRContext *ctx, mlir::Type storageType, + mlir::Type quantileType, + ArrayRef quantiles, + std::optional storageMin, + std::optional storageMax) { + return Base::get(ctx, storageType, quantileType, quantiles, storageMin, + storageMax); +} + +QuantileType QuantileType::getChecked( + function_ref emitError, mlir::MLIRContext *ctx, + mlir::Type storageType, mlir::Type quantileType, ArrayRef quantiles, + std::optional storageMin, std::optional storageMax) { + return Base::getChecked(emitError, ctx, storageType, quantileType, quantiles, + storageMin, storageMax); +} + +LogicalResult QuantileType::verifyInvariants( + function_ref emitError, Type storageType, + Type quantileType, ArrayRef quantiles, + std::optional storageMin, std::optional storageMax) { + if (!storageType.isIntOrFloat()) + return emitError() << "storage type must be an integer or float type"; + if (!llvm::isa(quantileType) && + !llvm::isa(quantileType)) + return emitError() << "quantile type must be a float or integer type"; + if (quantiles.empty()) + return emitError() << "quantile values must not be empty"; + if (storageMin.has_value() != storageMax.has_value()) + return emitError() + << "storage min and max must both be specified or both omitted"; + if (storageMin && storageMax && *storageMin >= *storageMax) + return emitError() << "storage min must be less than storage max"; + + unsigned width = storageType.getIntOrFloatBitWidth(); + bool isSigned = !llvm::isa(storageType) || + llvm::cast(storageType).isSigned(); + auto effectiveMin = + storageMin.value_or(isSigned ? -(1LL << (width - 1)) : 0LL); + auto effectiveMax = storageMax.value_or(isSigned ? (1LL << (width - 1)) - 1 + : (1LL << width) - 1); + auto expectedSize = effectiveMax - effectiveMin + 1; + if (static_cast(quantiles.size()) != expectedSize) + return emitError() << "quantile LUT size (" << quantiles.size() + << ") must equal the number of representable storage " + "values (" + << expectedSize << ")"; + + for (double v : quantiles) + if (std::isnan(v) || std::isinf(v)) + return emitError() + << "quantile values must be finite (no NaN or infinity)"; + + return success(); +} + +bool QuantileType::classof(mlir::Type type) { + return type.getTypeID() == mlir::TypeID::get(); +} + +mlir::Type QuantileType::getStorageType() const { + return static_cast(impl)->getStorageType(); +} + +mlir::Type QuantileType::getQuantileType() const { + return static_cast(impl)->getQuantileType(); +} + +ArrayRef QuantileType::getQuantiles() const { + return static_cast(impl)->getQuantiles(); +} + +std::optional QuantileType::getStorageMin() const { + return static_cast(impl)->getStorageMin(); +} + +std::optional QuantileType::getStorageMax() const { + return static_cast(impl)->getStorageMax(); +} + +bool QuantileType::shouldDefaultToSigned() const { + if (auto intType = mlir::dyn_cast(getStorageType())) + return intType.isSigned(); + // Float types default to signed. + return true; +} + +unsigned QuantileType::getStorageWidth() const { + return getStorageType().getIntOrFloatBitWidth(); +} + +int64_t QuantileType::getDefaultMaximum(bool isSigned) const { + if (auto explicitMax = getStorageMax()) + return *explicitMax; + if (isSigned) + return (1LL << (getStorageWidth() - 1)) - 1; + return (1LL << getStorageWidth()) - 1; +} + +int64_t QuantileType::getDefaultMinimum(bool isSigned) const { + if (auto explicitMin = getStorageMin()) + return *explicitMin; + if (isSigned) + return -(1LL << (getStorageWidth() - 1)); + return 0; +} + +std::string QuantileType::getStorageTypeName(bool isSigned) const { + std::string result = "!quant.quantile<"; + llvm::raw_string_ostream os(result); + os << getStorageType() << ":" << getQuantileType() << ", {"; + ArrayRef quantiles = this->getQuantiles(); + llvm::interleave( + llvm::seq(0, quantiles.size()), os, + [&](size_t index) { os << quantiles[index]; }, ","); + os << "}"; + if (auto minVal = getStorageMin()) + if (auto maxVal = getStorageMax()) + os << ", <" << *minVal << ":" << *maxVal << ">"; + os << ">"; + os.flush(); + return result; +} + +bool QuantileType::isPacked() const { return getStorageWidth() <= 4; } + +unsigned QuantileType::getLogicalBitWidth() const { return getStorageWidth(); } + +unsigned QuantileType::getElementsPerByte() const { + unsigned width = getStorageWidth(); + return width > 0 ? 8 / width : 0; +} + +std::optional QuantileType::getPreferredAlignmentBytes() const { + return std::nullopt; +} diff --git a/mlir/lib/Dialect/Quant/IR/TypeDetail.h b/mlir/lib/Dialect/Quant/IR/TypeDetail.h index a43bce354c324..8834ee7901c18 100644 --- a/mlir/lib/Dialect/Quant/IR/TypeDetail.h +++ b/mlir/lib/Dialect/Quant/IR/TypeDetail.h @@ -422,6 +422,86 @@ struct CalibratedQuantizedTypeStorage : public QuantizedTypeStorage { double max; }; +struct QuantileTypeStorage : public mlir::TypeStorage { + mlir::Type storageType; + mlir::Type quantileType; + const double *quantilesElements; + size_t quantilesParamsSize; + std::optional storageMin; + std::optional storageMax; + + struct KeyTy { + KeyTy(mlir::Type storageType, mlir::Type quantileType, + ArrayRef quantiles, + std::optional storageMin = std::nullopt, + std::optional storageMax = std::nullopt) + : storageType(storageType), quantileType(quantileType), + quantiles(quantiles), storageMin(storageMin), storageMax(storageMax) { + } + + mlir::Type storageType; + mlir::Type quantileType; + ArrayRef quantiles; + std::optional storageMin; + std::optional storageMax; + + mlir::Type getQuantileType() const { return quantileType; } + ArrayRef getQuantiles() const { return quantiles; } + + bool operator==(const KeyTy &other) const { + return storageType == other.storageType && + quantileType == other.quantileType && + quantiles == other.quantiles && storageMin == other.storageMin && + storageMax == other.storageMax; + } + + static llvm::hash_code hashOptInt(std::optional opt) { + return opt ? llvm::hash_combine(true, *opt) + : llvm::hash_combine(false, int64_t{0}); + } + + unsigned getHashValue() const { + const int64_t *quantilesCast = + llvm::bit_cast(quantiles.data()); + ArrayRef quantilesBits(quantilesCast, quantiles.size()); + return static_cast(llvm::hash_combine( + llvm::hash_combine_range(quantilesBits.begin(), quantilesBits.end()), + storageType, quantileType, hashOptInt(storageMin), + hashOptInt(storageMax))); + } + }; + + bool operator==(const KeyTy &key) const { + return storageType == key.storageType && quantileType == key.quantileType && + getQuantiles() == key.quantiles && storageMin == key.storageMin && + storageMax == key.storageMax; + } + + QuantileTypeStorage(const KeyTy &key, ArrayRef quantiles) + : storageType(key.storageType), quantileType(key.quantileType), + quantilesElements(quantiles.data()), + quantilesParamsSize(quantiles.size()), storageMin(key.storageMin), + storageMax(key.storageMax) {} + + static QuantileTypeStorage *construct(mlir::TypeStorageAllocator &allocator, + KeyTy key) { + ArrayRef quantiles = allocator.copyInto(key.quantiles); + return new (allocator.allocate()) + QuantileTypeStorage(key, quantiles); + } + + static unsigned hashKey(const KeyTy &key) { return key.getHashValue(); } + + ArrayRef getQuantiles() const { + return ArrayRef(quantilesElements, quantilesParamsSize); + } + + mlir::Type getStorageType() const { return storageType; } + mlir::Type getQuantileType() const { return quantileType; } + std::optional getStorageMin() const { return storageMin; } + std::optional getStorageMax() const { return storageMax; } +}; + } // namespace detail } // namespace quant } // namespace mlir diff --git a/mlir/lib/Dialect/Quant/IR/TypeParser.cpp b/mlir/lib/Dialect/Quant/IR/TypeParser.cpp index c6a6881b46f26..6724a66ddfede 100644 --- a/mlir/lib/Dialect/Quant/IR/TypeParser.cpp +++ b/mlir/lib/Dialect/Quant/IR/TypeParser.cpp @@ -11,6 +11,7 @@ #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/IR/Location.h" +#include "mlir/IR/QuantStorageTypeInterface.h" #include "mlir/IR/Types.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/Format.h" @@ -21,9 +22,9 @@ using namespace mlir; using namespace quant; -static IntegerType parseStorageType(DialectAsmParser &parser, bool &isSigned) { +static Type parseStorageType(DialectAsmParser &parser, bool &isSigned) { auto typeLoc = parser.getCurrentLocation(); - IntegerType type; + Type type; // Parse storage type (alpha_ident, integer_literal). StringRef identifier; @@ -32,20 +33,30 @@ static IntegerType parseStorageType(DialectAsmParser &parser, bool &isSigned) { if (result.has_value()) { if (!succeeded(*result)) return nullptr; - isSigned = !type.isUnsigned(); - storageTypeWidth = type.getWidth(); - } else if (succeeded(parser.parseKeyword(&identifier))) { - // Otherwise, this must be an unsigned integer (`u` integer-literal). - if (!identifier.consume_front("u")) { + + if (auto quantStorageTypeInterface = + llvm::dyn_cast(type)) { + // Returns true if the type defaults to signed (e.g., si8, i8 or float + // types), false if it defaults to unsigned. + isSigned = quantStorageTypeInterface.shouldDefaultToSigned(); + storageTypeWidth = quantStorageTypeInterface.getStorageWidth(); + } else { parser.emitError(typeLoc, "illegal storage type prefix"); return nullptr; } - if (identifier.getAsInteger(10, storageTypeWidth)) { - parser.emitError(typeLoc, "expected storage type width"); + } else if (succeeded(parser.parseKeyword(&identifier))) { + // Otherwise, this must be an unsigned integer (`u` integer-literal) + if (identifier.consume_front("u")) { + if (identifier.getAsInteger(10, storageTypeWidth)) { + parser.emitError(typeLoc, "expected storage type width"); + return nullptr; + } + isSigned = false; + type = parser.getBuilder().getIntegerType(storageTypeWidth); + } else { + parser.emitError(typeLoc, "illegal storage type prefix"); return nullptr; } - isSigned = false; - type = parser.getBuilder().getIntegerType(storageTypeWidth); } else { return nullptr; } @@ -60,35 +71,45 @@ static IntegerType parseStorageType(DialectAsmParser &parser, bool &isSigned) { return type; } -static ParseResult parseStorageRange(DialectAsmParser &parser, - IntegerType storageType, bool isSigned, - int64_t &storageTypeMin, +static ParseResult +checkStorageRange(DialectAsmParser &parser, int64_t storageTypeMin, + int64_t storageTypeMax, int64_t defaultStorageTypeMin, + int64_t defaultStorageTypeMax, SMLoc minLoc, SMLoc maxLoc) { + if (storageTypeMin < defaultStorageTypeMin) { + return parser.emitError(minLoc, "illegal storage type minimum: ") + << storageTypeMin; + } + if (storageTypeMax > defaultStorageTypeMax) { + return parser.emitError(maxLoc, "illegal storage type maximum: ") + << storageTypeMax; + } + return success(); +} + +static ParseResult parseStorageRange(DialectAsmParser &parser, Type storageType, + bool isSigned, int64_t &storageTypeMin, int64_t &storageTypeMax) { - int64_t defaultIntegerMin = QuantizedType::getDefaultMinimumForInteger( - isSigned, storageType.getWidth()); - int64_t defaultIntegerMax = QuantizedType::getDefaultMaximumForInteger( - isSigned, storageType.getWidth()); + auto quantStorageTypeInterface = + llvm::dyn_cast(storageType); + + int64_t defaultMin = quantStorageTypeInterface.getDefaultMinimum(isSigned); + int64_t defaultMax = quantStorageTypeInterface.getDefaultMaximum(isSigned); + if (failed(parser.parseOptionalLess())) { - storageTypeMin = defaultIntegerMin; - storageTypeMax = defaultIntegerMax; + storageTypeMin = defaultMin; + storageTypeMax = defaultMax; return success(); } // Explicit storage min and storage max. + // F8 and F4 min and max values are integers, so parseInteger() is used. SMLoc minLoc = parser.getCurrentLocation(), maxLoc; if (parser.parseInteger(storageTypeMin) || parser.parseColon() || parser.getCurrentLocation(&maxLoc) || parser.parseInteger(storageTypeMax) || parser.parseGreater()) return failure(); - if (storageTypeMin < defaultIntegerMin) { - return parser.emitError(minLoc, "illegal storage type minimum: ") - << storageTypeMin; - } - if (storageTypeMax > defaultIntegerMax) { - return parser.emitError(maxLoc, "illegal storage type maximum: ") - << storageTypeMax; - } - return success(); + return checkStorageRange(parser, storageTypeMin, storageTypeMax, defaultMin, + defaultMax, minLoc, maxLoc); } static FloatType parseExpressedTypeAndRange(DialectAsmParser &parser, @@ -118,7 +139,7 @@ static FloatType parseExpressedTypeAndRange(DialectAsmParser &parser, /// storage-type ::= (`i` | `u`) integer-literal /// expressed-type-spec ::= `:` `f` integer-literal static Type parseAnyType(DialectAsmParser &parser) { - IntegerType storageType; + Type storageType; FloatType expressedType; unsigned typeFlags = 0; int64_t storageTypeMin; @@ -167,10 +188,11 @@ isScaleInExpressedTypeRange(function_ref emitError, Type expressedType, double scale) { auto floatType = cast(expressedType); double minScale = - APFloat::getSmallest(floatType.getFloatSemantics()).convertToDouble(); + APFloat::getLargest(floatType.getFloatSemantics(), /*Negative=*/true) + .convertToDouble(); double maxScale = APFloat::getLargest(floatType.getFloatSemantics()).convertToDouble(); - if (scale < minScale || scale > maxScale) + if (scale < minScale || scale > maxScale || std::isnan(scale)) return emitError() << "scale " << scale << " out of expressed type range [" << minScale << ", " << maxScale << "]"; return success(); @@ -299,7 +321,7 @@ parseQuantParamListUntilRBrace(DialectAsmParser &parser, Type expressedType, return success(); } -/// Parses a UniformQuantizedType. +/// Parses a UniformQuantizedType /// /// uniform_type ::= uniform_per_layer /// | uniform_per_axis @@ -312,9 +334,39 @@ parseQuantParamListUntilRBrace(DialectAsmParser &parser, Type expressedType, /// block-size-info `,` scale-zero-tensor `>` /// storage-spec ::= storage-type (`<` storage-range `>`)? /// storage-range ::= integer-literal `:` integer-literal -/// storage-type ::= (`i` | `u`) integer-literal +/// storage-type ::= (`i` | `u`) integer-literal | `f8E5M2` | `f8E4M3FN` +// | `f4E2M1FN` | 'quantile' +/// expressed-type-spec ::= `:` `f` integer-literal +/// axis-spec ::= `:` integer-literal +/// scale-zero ::= scale (`:` zero-point)? +/// scale ::= float-literal +/// zero-point ::= integer-literal +/// scale-zero-list ::= scale-zero (`,` scale-zero)* +/// block-size-info ::= `{` `}` | `{` axis-block `:` (`,` axis-block)* `}` +/// axis-block ::= axis-spec `:` block-size-spec +/// block-size-spec ::= integer-literal +/// scale-zero-tensor ::= scale-zero-dense-exp | scale-zero-list +/// scale-zero-dense-exp ::= `{` +/// scale-zero-tensor (`,` scale-zero-tensor)* +/// `}` +/// +/// quantile_type ::= quantile_per_layer +/// | quantile_per_axis +/// quantile_per_layer ::= `quantile<` storage-spec quantile-type-spec +/// expressed-type-spec `,` quantiles-list `,` +/// scale-zero `>` +/// quantile_per_axis ::= `quantile<` storage-spec quantile-type-spec +/// expressed-type-spec axis-spec `,` quantiles-list +/// scale-zero-list `>` +/// storage-spec ::= storage-type (`<` storage-range `>`)? +/// storage-range ::= integer-literal `:` integer-literal +/// storage-type ::= (`i` | `u`) integer-literal | `f8E5M2` | `f8E4M3FN` +// | `f4E2M1FN` +/// quantile-type-spec ::= `:` ((`i` | `u` | `f`) integer-literal | `f8E5M2` +// | `f8E4M3FN` | `f4E2M1FN`) /// expressed-type-spec ::= `:` `f` integer-literal /// axis-spec ::= `:` integer-literal +/// quantiles-list ::= `{` quantile (`,` quantile)* `}` /// scale-zero ::= scale (`:` zero-point)? /// scale ::= float-literal /// zero-point ::= integer-literal @@ -326,8 +378,9 @@ parseQuantParamListUntilRBrace(DialectAsmParser &parser, Type expressedType, /// scale-zero-dense-exp ::= `{` /// scale-zero-tensor (`,` scale-zero-tensor)* /// `}` -static Type parseUniformType(DialectAsmParser &parser) { - IntegerType storageType; +static Type parseUniformType(DialectAsmParser &parser, bool isQuantile) { + Type storageType; + Type quantileType; FloatType expressedType; unsigned typeFlags = 0; int64_t storageTypeMin; @@ -336,6 +389,7 @@ static Type parseUniformType(DialectAsmParser &parser) { bool isSubChannel = false; SmallVector quantizedDimensions; SmallVector blockSizes; + SmallVector quantiles; SmallVector scales; SmallVector zeroPoints; @@ -470,6 +524,60 @@ static Type parseCalibratedType(DialectAsmParser &parser) { return parser.getChecked(expressedType, min, max); } +static Type parseQuantileType(DialectAsmParser &parser) { + Type storageType; + Type quantileType; + SmallVector quantiles; + + if (parser.parseLess()) + return nullptr; + if (parser.parseType(storageType)) + return nullptr; + if (parser.parseColon()) + return nullptr; + if (parser.parseType(quantileType)) + return nullptr; + if (parser.parseComma()) + return nullptr; + if (parser.parseLBrace()) + return nullptr; + + // Allow empty braces `{}` — verify() will catch the empty quantile error. + if (failed(parser.parseOptionalRBrace())) { + do { + quantiles.emplace_back(); + if (parser.parseFloat(quantiles.back())) + return nullptr; + } while (succeeded(parser.parseOptionalComma())); + + if (parser.parseRBrace()) + return nullptr; + } + + // Optionally parse explicit storage range: `, min:max` (inside the outer + // `<>`). + std::optional storageMin, storageMax; + if (succeeded(parser.parseOptionalComma())) { + if (parser.parseLess()) + return nullptr; + int64_t minVal, maxVal; + if (parser.parseInteger(minVal) || parser.parseColon() || + parser.parseInteger(maxVal)) + return nullptr; + storageMin = minVal; + storageMax = maxVal; + if (parser.parseGreater()) + return nullptr; + } + + if (parser.parseGreater()) + return nullptr; + + mlir::MLIRContext *ctx = parser.getContext(); + return parser.getChecked(ctx, storageType, quantileType, + quantiles, storageMin, storageMax); +} + /// Parse a type registered to this dialect. Type QuantDialect::parseType(DialectAsmParser &parser) const { // All types start with an identifier that we switch on. @@ -478,11 +586,13 @@ Type QuantDialect::parseType(DialectAsmParser &parser) const { return nullptr; if (typeNameSpelling == "uniform") - return parseUniformType(parser); + return parseUniformType(parser, false); if (typeNameSpelling == "any") return parseAnyType(parser); if (typeNameSpelling == "calibrated") return parseCalibratedType(parser); + if (typeNameSpelling == "quantile") + return parseQuantileType(parser); parser.emitError(parser.getNameLoc(), "unknown quantized type " + typeNameSpelling); @@ -491,21 +601,37 @@ Type QuantDialect::parseType(DialectAsmParser &parser) const { static void printStorageType(QuantizedType type, DialectAsmPrinter &out) { // storage type - unsigned storageWidth = type.getStorageTypeIntegralWidth(); - bool isSigned = type.isSigned(); - if (isSigned) { - out << "i" << storageWidth; - } else { - out << "u" << storageWidth; - } + auto quantStorageTypeInterface = + llvm::dyn_cast(type.getStorageType()); + + out << quantStorageTypeInterface.getStorageTypeName(type.isSigned()); - // storageTypeMin and storageTypeMax if not default. if (type.hasStorageTypeBounds()) { out << "<" << type.getStorageTypeMin() << ":" << type.getStorageTypeMax() << ">"; } } +static void printQuantileType(Type quantileType, DialectAsmPrinter &out) { + if (auto intType = llvm::dyn_cast(quantileType)) { + const unsigned storageTypeWidth = intType.getWidth(); + if (intType.isUnsigned()) { + out << ":u" << storageTypeWidth; + } else { + out << ":i" << storageTypeWidth; + } + } else if (mlir::isa(quantileType)) { + out << ":f8E5M2"; + } else if (mlir::isa(quantileType)) { + out << ":f8E4M3FN"; + } else if (mlir::isa(quantileType)) { + out << ":f4E2M1FN"; + } else { + // Float types + out << ":" << quantileType; + } +} + static void printQuantParams(double scale, int64_t zeroPoint, DialectAsmPrinter &out) { out << scale; @@ -646,6 +772,23 @@ static void printCalibratedQuantizedType(CalibratedQuantizedType type, out << ">"; } +static void printQuantileType(QuantileType type, DialectAsmPrinter &out) { + out << "quantile<"; + out << type.getStorageType(); + out << ":"; + out << type.getQuantileType(); + out << ", {"; + ArrayRef quantiles = type.getQuantiles(); + llvm::interleave( + llvm::seq(0, quantiles.size()), out, + [&](size_t index) { out << quantiles[index]; }, ","); + out << "}"; + if (auto minVal = type.getStorageMin()) + if (auto maxVal = type.getStorageMax()) + out << ", <" << *minVal << ":" << *maxVal << ">"; + out << ">"; +} + /// Print a type registered to this dialect. void QuantDialect::printType(Type type, DialectAsmPrinter &os) const { if (auto anyType = llvm::dyn_cast(type)) @@ -654,11 +797,13 @@ void QuantDialect::printType(Type type, DialectAsmPrinter &os) const { printUniformQuantizedType(uniformType, os); else if (auto perAxisType = llvm::dyn_cast(type)) printUniformQuantizedPerAxisType(perAxisType, os); + else if (auto calibratedType = llvm::dyn_cast(type)) + printCalibratedQuantizedType(calibratedType, os); else if (auto perAxisType = llvm::dyn_cast(type)) printUniformQuantizedSubChannelType(perAxisType, os); - else if (auto calibratedType = llvm::dyn_cast(type)) - printCalibratedQuantizedType(calibratedType, os); + else if (auto quantileType = llvm::dyn_cast(type)) + printQuantileType(quantileType, os); else llvm_unreachable("Unhandled quantized type"); } diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp index 00c31a1500e17..dbea050b554ea 100644 --- a/mlir/lib/Dialect/SCF/IR/SCF.cpp +++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp @@ -4273,14 +4273,15 @@ LogicalResult scf::IndexSwitchOp::verify() { << "see yield operation here"; } for (auto [idx, result, operand] : - llvm::zip(llvm::seq(0, getNumResults()), getResultTypes(), - yield.getOperandTypes())) { - if (result == operand) + llvm::enumerate(getResultTypes(), yield.getOperands())) { + if (!operand) + return yield.emitOpError() << "operand " << idx << " is null\n"; + if (result == operand.getType()) continue; return (emitOpError("expected result #") << idx << " of each region to be " << result) .attachNote(yield.getLoc()) - << name << " returns " << operand << " here"; + << name << " returns " << operand.getType() << " here"; } return success(); }; diff --git a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp index 09326242eec2a..91ce8bb0c0ea2 100644 --- a/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/StructuralTypeConversions.cpp @@ -185,6 +185,30 @@ class ConvertWhileOpTypes }; } // namespace +namespace { +class ConvertIndexSwitchOpTypes + : public Structural1ToNConversionPattern { +public: + using Structural1ToNConversionPattern::Structural1ToNConversionPattern; + + std::optional + convertSourceOp(IndexSwitchOp op, OneToNOpAdaptor adaptor, + ConversionPatternRewriter &rewriter, + TypeRange dstTypes) const { + auto newOp = + IndexSwitchOp::create(rewriter, op.getLoc(), dstTypes, op.getArg(), + op.getCases(), op.getNumCases()); + + for (unsigned i = 0u; i < op.getNumRegions(); i++) { + auto &dstRegion = newOp.getRegion(i); + rewriter.inlineRegionBefore(op.getRegion(i), dstRegion, dstRegion.end()); + } + return newOp; + } +}; +} // namespace + namespace { // When the result types of a ForOp/IfOp get changed, the operand types of the // corresponding yield op need to be changed. In order to trigger the @@ -219,19 +243,19 @@ class ConvertConditionOpTypes : public OpConversionPattern { void mlir::scf::populateSCFStructuralTypeConversions( const TypeConverter &typeConverter, RewritePatternSet &patterns) { patterns.add( - typeConverter, patterns.getContext()); + ConvertWhileOpTypes, ConvertConditionOpTypes, + ConvertIndexSwitchOpTypes>(typeConverter, patterns.getContext()); } void mlir::scf::populateSCFStructuralTypeConversionTarget( const TypeConverter &typeConverter, ConversionTarget &target) { - target.addDynamicallyLegalOp([&](Operation *op) { + target.addDynamicallyLegalOp([&](Operation *op) { return typeConverter.isLegal(op->getResultTypes()); }); target.addDynamicallyLegalOp([&](scf::YieldOp op) { // We only have conversions for a subset of ops that use scf.yield // terminators. - if (!isa(op->getParentOp())) + if (!isa(op->getParentOp())) return true; return typeConverter.isLegal(op.getOperandTypes()); }); diff --git a/mlir/lib/Dialect/UB/IR/CMakeLists.txt b/mlir/lib/Dialect/UB/IR/CMakeLists.txt index 84125ea0b5718..ef9cf277b8ba5 100644 --- a/mlir/lib/Dialect/UB/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/UB/IR/CMakeLists.txt @@ -9,5 +9,6 @@ add_mlir_dialect_library(MLIRUBDialect MLIRUBOpsInterfacesIncGen LINK_LIBS PUBLIC + MLIRTransformUtils MLIRIR ) diff --git a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp index 1cded38c4419e..36059e553d30e 100644 --- a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp +++ b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp @@ -272,7 +272,7 @@ std::optional constantTripCount(OpFoldResult lb, OpFoldResult ub, if (!ubConstant) return std::nullopt; std::optional stepConstant = getConstantIntValue(step); - if (!stepConstant) + if (!stepConstant || *stepConstant == 0) return std::nullopt; return llvm::divideCeilSigned(*ubConstant - *lbConstant, *stepConstant); diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp index 8a08a157b25d7..7d615bfc12984 100644 --- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp +++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp @@ -4237,28 +4237,35 @@ class StridedSliceBroadcast final auto dstVecType = llvm::cast(op.getType()); unsigned dstRank = dstVecType.getRank(); unsigned rankDiff = dstRank - srcRank; - // Check if the most inner dimensions of the source of the broadcast are the - // same as the destination of the extract. If this is the case we can just - // use a broadcast as the original dimensions are untouched. - bool lowerDimMatch = true; + // Source dimensions can be broadcasted (1 -> n with n > 1) or sliced + // (n -> m with n > m). If they are originally both broadcasted *and* + // sliced, this can be simplified to just broadcasting. + bool needsSlice = false; for (unsigned i = 0; i < srcRank; i++) { - if (srcVecType.getDimSize(i) != dstVecType.getDimSize(i + rankDiff)) { - lowerDimMatch = false; + if (srcVecType.getDimSize(i) != 1 && + srcVecType.getDimSize(i) != dstVecType.getDimSize(i + rankDiff)) { + needsSlice = true; break; } } Value source = broadcast.getSource(); - // If the inner dimensions don't match, it means we need to extract from the - // source of the orignal broadcast and then broadcast the extracted value. - // We also need to handle degenerated cases where the source is effectively - // just a single scalar. - bool isScalarSrc = (srcRank == 0 || srcVecType.getNumElements() == 1); - if (!lowerDimMatch && !isScalarSrc) { + if (needsSlice) { + SmallVector offsets = + getI64SubArray(op.getOffsets(), /*dropFront=*/rankDiff); + SmallVector sizes = + getI64SubArray(op.getSizes(), /*dropFront=*/rankDiff); + for (unsigned i = 0; i < srcRank; i++) { + if (srcVecType.getDimSize(i) == 1) { + // In case this dimension was broadcasted *and* sliced, the offset + // and size need to be updated now that there is no broadcast before + // the slice. + offsets[i] = 0; + sizes[i] = 1; + } + } source = rewriter.create( - op->getLoc(), source, - getI64SubArray(op.getOffsets(), /* dropFront=*/rankDiff), - getI64SubArray(op.getSizes(), /* dropFront=*/rankDiff), - getI64SubArray(op.getStrides(), /* dropFront=*/rankDiff)); + op->getLoc(), source, offsets, sizes, + getI64SubArray(op.getStrides(), /*dropFront=*/rankDiff)); } rewriter.replaceOpWithNewOp(op, op.getType(), source); return success(); diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index f95ad290a1981..2d0107f105fc2 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -418,6 +418,21 @@ class AsmPrinter::Impl { /// Returns the output stream of the printer. raw_ostream &getStream() { return os; } + /// Print a newline and indent the printer to the start of the current + /// operation/attribute/type. + /// Note: For attributes and types this method should only be used in + /// custom dialects. Usage in MLIR dialects is disallowed. + void printNewline() { + os << newLine; + os.indent(currentIndent); + } + + /// Increase indentation. + void increaseIndent() { currentIndent += indentWidth; } + + /// Decrease indentation. + void decreaseIndent() { currentIndent -= indentWidth; } + template inline void interleaveComma(const Container &c, UnaryFunctor eachFn) const { llvm::interleaveComma(c, os, eachFn); @@ -532,6 +547,12 @@ class AsmPrinter::Impl { /// A tracker for the number of new lines emitted during printing. NewLineCounter newLine; + + /// The number of spaces used as an indent. + const static unsigned indentWidth = 2; + + /// This is the current indentation level for nested structures. + unsigned currentIndent = 0; }; } // namespace mlir @@ -1004,6 +1025,9 @@ class DummyAliasDialectAsmPrinter : public DialectAsmPrinter { /// The following are hooks of `DialectAsmPrinter` that are not necessary for /// determining potential aliases. + void printNewline() override {} + void increaseIndent() override {} + void decreaseIndent() override {} void printFloat(const APFloat &) override {} void printKeywordOrString(StringRef) override {} void printString(StringRef) override {} @@ -2893,6 +2917,13 @@ void AsmPrinter::Impl::printDialectAttribute(Attribute attr) { { llvm::raw_string_ostream attrNameStr(attrName); Impl subPrinter(attrNameStr, state); + + // The values of currentIndent and newLine are assigned to the created + // subprinter, so that the indent level and number of printed lines can be + // tracked. + subPrinter.currentIndent = currentIndent; + subPrinter.newLine = newLine; + DialectAsmPrinter printer(subPrinter); dialect.printAttribute(attr, printer); } @@ -2907,6 +2938,13 @@ void AsmPrinter::Impl::printDialectType(Type type) { { llvm::raw_string_ostream typeNameStr(typeName); Impl subPrinter(typeNameStr, state); + + // The values of currentIndent and newLine are assigned to the created + // subprinter, so that the indent level and number of printed lines can be + // tracked. + subPrinter.currentIndent = currentIndent; + subPrinter.newLine = newLine; + DialectAsmPrinter printer(subPrinter); dialect.printType(type, printer); } @@ -2947,6 +2985,21 @@ raw_ostream &AsmPrinter::getStream() const { return impl->getStream(); } +void AsmPrinter::printNewline() { + assert(impl && "expected AsmPrinter::printNewLine to be overriden"); + impl->printNewline(); +} + +void AsmPrinter::increaseIndent() { + assert(impl && "expected AsmPrinter::increaseIndent to be overriden"); + impl->increaseIndent(); +} + +void AsmPrinter::decreaseIndent() { + assert(impl && "expected AsmPrinter::decreaseIndent to be overriden"); + impl->decreaseIndent(); +} + /// Print the given floating point value in a stablized form. void AsmPrinter::printFloat(const APFloat &value) { assert(impl && "expected AsmPrinter::printFloat to be overriden"); @@ -3277,19 +3330,6 @@ class OperationPrinter : public AsmPrinter::Impl, private OpAsmPrinter { printTrailingLocation(loc); } - /// Print a newline and indent the printer to the start of the current - /// operation. - void printNewline() override { - os << newLine; - os.indent(currentIndent); - } - - /// Increase indentation. - void increaseIndent() override { currentIndent += indentWidth; } - - /// Decrease indentation. - void decreaseIndent() override { currentIndent -= indentWidth; } - /// Print a block argument in the usual format of: /// %ssaName : type {attr1=42} loc("here") /// where location printing is controlled by the standard internal option. @@ -3415,12 +3455,6 @@ class OperationPrinter : public AsmPrinter::Impl, private OpAsmPrinter { // top-level we start with "builtin" as the default, so that the top-level // `module` operation prints as-is. SmallVector defaultDialectStack{"builtin"}; - - /// The number of spaces used for indenting nested operations. - const static unsigned indentWidth = 2; - - // This is the current indentation level for nested structures. - unsigned currentIndent = 0; }; } // namespace @@ -4056,8 +4090,13 @@ void Value::print(raw_ostream &os, AsmState &state) const { << "' at index: " << arg.getArgNumber(); } +raw_ostream &mlir::operator<<(raw_ostream &os, Value value) { + value.print(os, OpPrintingFlags().useLocalScope()); + return os; +} + void Value::dump() const { - print(llvm::errs()); + print(llvm::errs(), OpPrintingFlags().useLocalScope()); llvm::errs() << "\n"; } diff --git a/mlir/lib/IR/AttributeDetail.h b/mlir/lib/IR/AttributeDetail.h index 26d40ac3a38f6..cb9d21bf3e611 100644 --- a/mlir/lib/IR/AttributeDetail.h +++ b/mlir/lib/IR/AttributeDetail.h @@ -19,11 +19,9 @@ #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/IntegerSet.h" #include "mlir/IR/MLIRContext.h" -#include "mlir/Support/StorageUniquer.h" -#include "mlir/Support/ThreadLocalCache.h" #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/Allocator.h" +#include namespace mlir { namespace detail { @@ -396,27 +394,30 @@ class DistinctAttributeUniquer { Attribute referencedAttr); }; -/// An allocator for distinct attribute storage instances. It uses thread local -/// bump pointer allocators stored in a thread local cache to ensure the storage -/// is freed after the destruction of the distinct attribute allocator. -class DistinctAttributeAllocator { +/// An allocator for distinct attribute storage instances. Uses a synchronized +/// BumpPtrAllocator to ensure thread-safety. The allocated storage is deleted +/// when the DistinctAttributeAllocator is destroyed. +class DistinctAttributeAllocator final { public: DistinctAttributeAllocator() = default; - DistinctAttributeAllocator(DistinctAttributeAllocator &&) = delete; DistinctAttributeAllocator(const DistinctAttributeAllocator &) = delete; DistinctAttributeAllocator & operator=(const DistinctAttributeAllocator &) = delete; - /// Allocates a distinct attribute storage using a thread local bump pointer - /// allocator to enable synchronization free parallel allocations. DistinctAttrStorage *allocate(Attribute referencedAttr) { - return new (allocatorCache.get().Allocate()) + std::scoped_lock guard(allocatorMutex); + return new (allocator.Allocate()) DistinctAttrStorage(referencedAttr); - } + }; private: - ThreadLocalCache allocatorCache; + /// Used to allocate distict attribute storages. The managed memory is freed + /// automatically when the allocator instance is destroyed. + llvm::BumpPtrAllocator allocator; + + /// Used to lock access to the allocator. + std::mutex allocatorMutex; }; } // namespace detail } // namespace mlir diff --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp index 1604ebba190a1..e2624cb7f3eb2 100644 --- a/mlir/lib/IR/BuiltinTypes.cpp +++ b/mlir/lib/IR/BuiltinTypes.cpp @@ -486,7 +486,8 @@ bool mlir::detail::isSupportedMemorySpace(Attribute memorySpace) { return true; // Supported built-in attributes. - if (llvm::isa(memorySpace)) + if (llvm::isa(memorySpace)) return true; // Allow custom dialect attributes. diff --git a/mlir/lib/IR/CMakeLists.txt b/mlir/lib/IR/CMakeLists.txt index 4cabac185171c..9b8ea39b526c5 100644 --- a/mlir/lib/IR/CMakeLists.txt +++ b/mlir/lib/IR/CMakeLists.txt @@ -30,6 +30,7 @@ add_mlir_library(MLIRIR Operation.cpp OperationSupport.cpp PatternMatch.cpp + QuantStorageTypeInterface.cpp Region.cpp RegionKindInterface.cpp SymbolTable.cpp @@ -61,6 +62,7 @@ add_mlir_library(MLIRIR MLIRCastInterfacesIncGen MLIRDataLayoutInterfacesIncGen MLIROpAsmInterfaceIncGen + MLIRQuantStorageTypeInterfaceIncGen MLIRRegionKindInterfaceIncGen MLIRSideEffectInterfacesIncGen MLIRSymbolInterfacesIncGen @@ -69,4 +71,3 @@ add_mlir_library(MLIRIR LINK_LIBS PUBLIC MLIRSupport ) - diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp index 716d9c85a377d..77b4eba06f5c6 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/RWMutex.h" #include "llvm/Support/ThreadPool.h" @@ -370,6 +371,10 @@ void MLIRContext::registerActionHandler(HandlerTy handler) { getImpl().actionHandler = std::move(handler); } +const MLIRContext::HandlerTy &MLIRContext::getActionHandler() { + return getImpl().actionHandler; +} + /// Dispatch the provided action to the handler if any, or just execute it. void MLIRContext::executeActionInternal(function_ref actionFn, const tracing::Action &action) { @@ -883,6 +888,8 @@ int OperationName::UnregisteredOpModel::getOpPropertyByteSize() { void OperationName::UnregisteredOpModel::initProperties( OperationName opName, OpaqueProperties storage, OpaqueProperties init) { new (storage.as()) Attribute(); + if (init) + *storage.as() = *init.as(); } void OperationName::UnregisteredOpModel::deleteProperties( OpaqueProperties prop) { diff --git a/mlir/lib/IR/QuantStorageTypeInterface.cpp b/mlir/lib/IR/QuantStorageTypeInterface.cpp new file mode 100644 index 0000000000000..e9c27187f3f33 --- /dev/null +++ b/mlir/lib/IR/QuantStorageTypeInterface.cpp @@ -0,0 +1,17 @@ +//===- QuantStorageTypeInterface.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 "mlir/IR/QuantStorageTypeInterface.h" + +using namespace mlir; + +//===----------------------------------------------------------------------===// +/// Tablegen Interface Definitions +//===----------------------------------------------------------------------===// + +#include "mlir/IR/QuantStorageTypeInterface.cpp.inc" diff --git a/mlir/lib/IR/SymbolTable.cpp b/mlir/lib/IR/SymbolTable.cpp index aaa4d5617eb4f..fa028b905f960 100644 --- a/mlir/lib/IR/SymbolTable.cpp +++ b/mlir/lib/IR/SymbolTable.cpp @@ -56,8 +56,10 @@ collectValidReferencesFor(Operation *symbol, StringAttr symbolName, StringAttr symbolNameId = StringAttr::get(ctx, SymbolTable::getSymbolAttrName()); do { - // Each parent of 'symbol' should define a symbol table. - if (!symbolTableOp->hasTrait()) + // Each parent of 'symbol' should define a symbol table or be a symbol + // container + if (!symbolTableOp->hasTrait() && + !symbolTableOp->hasTrait()) return failure(); // Each parent of 'symbol' should also be a symbol. StringAttr symbolTableName = getNameIfSymbol(symbolTableOp, symbolNameId); @@ -117,7 +119,8 @@ walkSymbolTable(Operation *op, /// Build a symbol table with the symbols within the given operation. SymbolTable::SymbolTable(Operation *symbolTableOp) : symbolTableOp(symbolTableOp) { - assert(symbolTableOp->hasTrait() && + assert((symbolTableOp->hasTrait() || + symbolTableOp->hasTrait()) && "expected operation to have SymbolTable trait"); assert(symbolTableOp->getNumRegions() == 1 && "expected operation to have a single region"); @@ -384,7 +387,8 @@ void SymbolTable::walkSymbolTables( /// was found. Operation *SymbolTable::lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol) { - assert(symbolTableOp->hasTrait()); + assert(symbolTableOp->hasTrait() || + symbolTableOp->hasTrait()); Region ®ion = symbolTableOp->getRegion(0); if (region.empty()) return nullptr; @@ -425,7 +429,8 @@ static LogicalResult lookupSymbolInImpl( return success(); // Verify that the root is also a symbol table. - if (!symbolTableOp->hasTrait()) + if (!symbolTableOp->hasTrait() && + !symbolTableOp->hasTrait()) return failure(); // Otherwise, lookup each of the nested non-leaf references and ensure that @@ -702,7 +707,8 @@ static SmallVector collectSymbolScopes(Operation *symbol, Operation *limitIt = symbol->getParentOp(); for (size_t i = 0, e = references.size(); i != e; ++i, limitIt = limitIt->getParentOp()) { - assert(limitIt->hasTrait()); + assert(limitIt->hasTrait() || + limitIt->hasTrait()); scopes.push_back({references[i], &limitIt->getRegion(0)}); } return scopes; @@ -870,23 +876,27 @@ bool SymbolTable::symbolKnownUseEmpty(Operation *symbol, Region *from) { /// Generates a new symbol reference attribute with a new leaf reference. static SymbolRefAttr generateNewRefAttr(SymbolRefAttr oldAttr, - FlatSymbolRefAttr newLeafAttr) { + SymbolRefAttr newLeafAttr) { if (llvm::isa(oldAttr)) return newLeafAttr; auto nestedRefs = llvm::to_vector<2>(oldAttr.getNestedReferences()); - nestedRefs.back() = newLeafAttr; + nestedRefs.back() = FlatSymbolRefAttr::get(newLeafAttr.getRootReference()); + + nestedRefs.append(newLeafAttr.getNestedReferences().begin(), + newLeafAttr.getNestedReferences().end()); + return SymbolRefAttr::get(oldAttr.getRootReference(), nestedRefs); } /// The implementation of SymbolTable::replaceAllSymbolUses below. template -static LogicalResult -replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) { +static LogicalResult replaceAllSymbolUsesImpl(SymbolT symbol, + SymbolRefAttr newSymbol, + IRUnitT *limit) { // Generate a new attribute to replace the given attribute. - FlatSymbolRefAttr newLeafAttr = FlatSymbolRefAttr::get(newSymbol); for (SymbolScope &scope : collectSymbolScopes(symbol, limit)) { SymbolRefAttr oldAttr = scope.symbol; - SymbolRefAttr newAttr = generateNewRefAttr(scope.symbol, newLeafAttr); + SymbolRefAttr newAttr = generateNewRefAttr(scope.symbol, newSymbol); AttrTypeReplacer replacer; replacer.addReplacement( [&](SymbolRefAttr attr) -> std::pair { @@ -899,11 +909,13 @@ replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) { auto oldNestedRefs = oldAttr.getNestedReferences(); auto nestedRefs = attr.getNestedReferences(); if (oldNestedRefs.empty()) - return {SymbolRefAttr::get(newSymbol, nestedRefs), - WalkResult::skip()}; + return {newAttr, WalkResult::skip()}; auto newNestedRefs = llvm::to_vector<4>(nestedRefs); - newNestedRefs[oldNestedRefs.size() - 1] = newLeafAttr; + newNestedRefs[oldNestedRefs.size() - 1] = + FlatSymbolRefAttr::get(newAttr.getRootReference()); + newNestedRefs.append(newAttr.getNestedReferences().begin(), + newAttr.getNestedReferences().end()); return {SymbolRefAttr::get(attr.getRootReference(), newNestedRefs), WalkResult::skip()}; } @@ -928,21 +940,37 @@ replaceAllSymbolUsesImpl(SymbolT symbol, StringAttr newSymbol, IRUnitT *limit) { LogicalResult SymbolTable::replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Operation *from) { - return replaceAllSymbolUsesImpl(oldSymbol, newSymbol, from); + auto newSymRef = mlir::FlatSymbolRefAttr::get(newSymbol); + return replaceAllSymbolUsesImpl(oldSymbol, newSymRef, from); } LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, StringAttr newSymbol, Operation *from) { - return replaceAllSymbolUsesImpl(oldSymbol, newSymbol, from); + auto newSymRef = mlir::FlatSymbolRefAttr::get(newSymbol); + return replaceAllSymbolUsesImpl(oldSymbol, newSymRef, from); } LogicalResult SymbolTable::replaceAllSymbolUses(StringAttr oldSymbol, StringAttr newSymbol, Region *from) { - return replaceAllSymbolUsesImpl(oldSymbol, newSymbol, from); + auto newSymRef = mlir::FlatSymbolRefAttr::get(newSymbol); + return replaceAllSymbolUsesImpl(oldSymbol, newSymRef, from); } LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, StringAttr newSymbol, Region *from) { + auto newSymRef = mlir::FlatSymbolRefAttr::get(newSymbol); + return replaceAllSymbolUsesImpl(oldSymbol, newSymRef, from); +} + +LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, + SymbolRefAttr newSymbol, + Operation *from) { + return replaceAllSymbolUsesImpl(oldSymbol, newSymbol, from); +} + +LogicalResult SymbolTable::replaceAllSymbolUses(Operation *oldSymbol, + SymbolRefAttr newSymbol, + Region *from) { return replaceAllSymbolUsesImpl(oldSymbol, newSymbol, from); } @@ -1084,7 +1112,7 @@ SymbolUserMap::SymbolUserMap(SymbolTableCollection &symbolTable, } void SymbolUserMap::replaceAllUsesWith(Operation *symbol, - StringAttr newSymbolName) { + SymbolRefAttr newSymbolName) { auto it = symbolToUsers.find(symbol); if (it == symbolToUsers.end()) return; @@ -1111,6 +1139,11 @@ void SymbolUserMap::replaceAllUsesWith(Operation *symbol, } } +void SymbolUserMap::replaceAllUsesWith(Operation *symbol, + StringAttr newSymbolName) { + replaceAllUsesWith(symbol, mlir::FlatSymbolRefAttr::get(newSymbolName)); +} + //===----------------------------------------------------------------------===// // Visibility parsing implementation. //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp index dafec39fd5eb0..8ba352d2b1ab0 100644 --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -80,6 +80,12 @@ void Pass::copyOptionValuesFrom(const Pass *other) { passOptions.copyOptionValuesFrom(other->passOptions); } +/// Copy the option values from 'other', which are PassPipeline options. +/// Here we copy only those options that have the same argument name. +void Pass::copyOptionValuesFrom(const PassOptions &other) { + passOptions.matchAndCopyOptionValuesFrom(other); +} + /// Prints out the pass in the textual representation of pipelines. If this is /// an adaptor pass, print its pass managers. When `pretty` is true, the /// printed pipeline is formatted for readability. diff --git a/mlir/lib/Pass/PassCrashRecovery.cpp b/mlir/lib/Pass/PassCrashRecovery.cpp index b048ff9462392..c6fb1d737d508 100644 --- a/mlir/lib/Pass/PassCrashRecovery.cpp +++ b/mlir/lib/Pass/PassCrashRecovery.cpp @@ -414,14 +414,19 @@ struct FileReproducerStream : public mlir::ReproducerStream { LogicalResult PassManager::runWithCrashRecovery(Operation *op, AnalysisManager am) { + const bool threadingEnabled = getContext()->isMultithreadingEnabled(); crashReproGenerator->initialize(getPasses(), op, verifyPasses); // Safely invoke the passes within a recovery context. LogicalResult passManagerResult = failure(); llvm::CrashRecoveryContext recoveryContext; - recoveryContext.RunSafelyOnThread( - [&] { passManagerResult = runPasses(op, am); }); + const auto runPassesFn = [&] { passManagerResult = runPasses(op, am); }; + if (threadingEnabled) + recoveryContext.RunSafelyOnThread(runPassesFn); + else + recoveryContext.RunSafely(runPassesFn); crashReproGenerator->finalize(op, passManagerResult); + return passManagerResult; } diff --git a/mlir/lib/Pass/PassRegistry.cpp b/mlir/lib/Pass/PassRegistry.cpp index 7c294f08a32bb..ed5ab073b9159 100644 --- a/mlir/lib/Pass/PassRegistry.cpp +++ b/mlir/lib/Pass/PassRegistry.cpp @@ -277,6 +277,20 @@ void detail::PassOptions::copyOptionValuesFrom(const PassOptions &other) { std::get<0>(optionsIt)->copyValueFrom(*std::get<1>(optionsIt)); } +/// Copy only those options that have the same argument name. +void detail::PassOptions::matchAndCopyOptionValuesFrom( + const PassOptions &other) { + for (auto *optionsIt : other.options) { + const auto &it = llvm::find_if(options, [&](OptionBase *option) { + return option->getArgStr() == optionsIt->getArgStr(); + }); + + if (it != options.end()) { + (*it)->copyValueFrom(*optionsIt); + } + } +} + /// Parse in the next argument from the given options string. Returns a tuple /// containing [the key of the option, the value of the option, updated /// `options` string pointing after the parsed option]. diff --git a/mlir/lib/Support/Timing.cpp b/mlir/lib/Support/Timing.cpp index ac16eb7d224c9..e1e51965354b0 100644 --- a/mlir/lib/Support/Timing.cpp +++ b/mlir/lib/Support/Timing.cpp @@ -621,11 +621,17 @@ void mlir::applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm) { return; tm.setEnabled(options->timing); tm.setDisplayMode(options->displayMode); + tm.setOutput(createOutputStrategy(options->outputFormat, llvm::errs())); +} - std::unique_ptr printer; - if (options->outputFormat == OutputFormat::Text) - printer = std::make_unique(llvm::errs()); - else if (options->outputFormat == OutputFormat::Json) - printer = std::make_unique(llvm::errs()); - tm.setOutput(std::move(printer)); +std::unique_ptr +mlir::createOutputStrategy(DefaultTimingManager::OutputFormat fmt, + raw_ostream &os) { + switch (fmt) { + case OutputFormat::Text: + return std::make_unique(os); + case OutputFormat::Json: + return std::make_unique(os); + } + llvm_unreachable("Invalid output format"); } diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index 3185f28fe6681..f8ea6ee07447b 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -3395,6 +3395,7 @@ static llvm::omp::Directive convertCancellationConstructType( case omp::ClauseCancellationConstructType::Taskgroup: return llvm::omp::Directive::OMPD_taskgroup; } + llvm_unreachable("Unhandled cancellation construct type"); } static LogicalResult diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp index 31e0caa768113..9f2a5c761b5ce 100644 --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -508,8 +508,7 @@ performActions(raw_ostream &os, << "bytecode version while not emitting bytecode"; AsmState asmState(op.get(), OpPrintingFlags(), /*locationMap=*/nullptr, &fallbackResourceMap); - op.get()->print(os, asmState); - os << '\n'; + os << OpWithState(op.get(), asmState) << '\n'; return success(); } diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp index 608bdcb948176..1d7e2135e23e1 100644 --- a/mlir/lib/Transforms/RemoveDeadValues.cpp +++ b/mlir/lib/Transforms/RemoveDeadValues.cpp @@ -258,16 +258,22 @@ static SmallVector operandsToOpOperands(OperandRange operands) { static void processSimpleOp(Operation *op, RunLivenessAnalysis &la, DenseSet &nonLiveSet, RDVFinalCleanupList &cl) { - LDBG("Processing simple op: " << *op); if (!isMemoryEffectFree(op) || hasLive(op->getResults(), nonLiveSet, la)) { - LDBG("Simple op is not memory effect free or has live results, skipping: " - << *op); + LLVM_DEBUG({ + llvm::dbgs() + << "Simple op is not memory effect free or has live results, " + "preserving it: " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) << "\n"; + }); return; } - LDBG("Simple op has all dead results and is memory effect free, scheduling " - "for removal: " - << *op); + LLVM_DEBUG({ + llvm::dbgs() << "Simple op has all dead results and is memory effect free, " + "scheduling " + "for removal: " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) << "\n"; + }); cl.operations.push_back(op); collectNonLiveValues(nonLiveSet, op->getResults(), BitVector(op->getNumResults(), true)); @@ -345,8 +351,6 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module, // since it forwards only to non-live value(s) (%1#1). Operation *lastReturnOp = funcOp.back().getTerminator(); size_t numReturns = lastReturnOp->getNumOperands(); - if (numReturns == 0) - return; BitVector nonLiveRets(numReturns, true); for (SymbolTable::SymbolUse use : uses) { Operation *callOp = use.getUser(); @@ -368,6 +372,8 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module, cl.functions.push_back({funcOp, nonLiveArgs, nonLiveRets}); // Do (5) and (6). + if (numReturns == 0) + return; for (SymbolTable::SymbolUse use : uses) { Operation *callOp = use.getUser(); assert(isa(callOp) && "expected a call-like user"); @@ -727,19 +733,53 @@ static void processBranchOp(BranchOpInterface branchOp, RunLivenessAnalysis &la, /// Removes dead values collected in RDVFinalCleanupList. /// To be run once when all dead values have been collected. static void cleanUpDeadVals(RDVFinalCleanupList &list) { + LLVM_DEBUG({ llvm::dbgs() << "Starting cleanup of dead values...\n"; }); + // 1. Operations + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.operations.size() << " operations" + << "\n"; + }); for (auto &op : list.operations) { + LLVM_DEBUG({ + llvm::dbgs() << "Erasing operation: " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) << "\n"; + }); op->dropAllUses(); op->erase(); } // 2. Values + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.values.size() << " values" + << "\n"; + }); for (auto &v : list.values) { + LLVM_DEBUG( + { llvm::dbgs() << "Dropping all uses of value: " << v << "\n"; }); v.dropAllUses(); } // 3. Functions + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.functions.size() << " functions" + << "\n"; + }); for (auto &f : list.functions) { + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up function: " + << f.funcOp.getOperation()->getName() << "\n"; + }); + LLVM_DEBUG({ + llvm::dbgs() << " Erasing " << f.nonLiveArgs.count() + << " non-live arguments" + << "\n"; + }); + LLVM_DEBUG({ + llvm::dbgs() << " Erasing " << f.nonLiveRets.count() + << " non-live return values" + << "\n"; + }); // Some functions may not allow erasing arguments or results. These calls // return failure in such cases without modifying the function, so it's okay // to proceed. @@ -748,44 +788,99 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) { } // 4. Operands + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.operands.size() << " operand lists" + << "\n"; + }); for (OperationToCleanup &o : list.operands) { - if (o.op->getNumOperands() > 0) + if (o.op->getNumOperands() > 0) { + LLVM_DEBUG({ + llvm::dbgs() << "Erasing " << o.nonLive.count() + << " non-live operands from operation: " + << OpWithFlags(o.op, OpPrintingFlags().skipRegions()) + << "\n"; + }); o.op->eraseOperands(o.nonLive); + } } // 5. Results + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.results.size() << " result lists" + << "\n"; + }); for (auto &r : list.results) { + LLVM_DEBUG({ + llvm::dbgs() << "Erasing " << r.nonLive.count() + << " non-live results from operation: " + << OpWithFlags(r.op, OpPrintingFlags().skipRegions()) + << "\n"; + }); dropUsesAndEraseResults(r.op, r.nonLive); } // 6. Blocks + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.blocks.size() + << " block argument lists" + << "\n"; + }); for (auto &b : list.blocks) { // blocks that are accessed via multiple codepaths processed once if (b.b->getNumArguments() != b.nonLiveArgs.size()) continue; + LLVM_DEBUG({ + llvm::dbgs() << "Erasing " << b.nonLiveArgs.count() + << " non-live arguments from block: " << b.b << "\n"; + }); // it iterates backwards because erase invalidates all successor indexes for (int i = b.nonLiveArgs.size() - 1; i >= 0; --i) { if (!b.nonLiveArgs[i]) continue; + LLVM_DEBUG({ + llvm::dbgs() << " Erasing block argument " << i << ": " + << b.b->getArgument(i) << "\n"; + }); b.b->getArgument(i).dropAllUses(); b.b->eraseArgument(i); } } // 7. Successor Operands + LLVM_DEBUG({ + llvm::dbgs() << "Cleaning up " << list.successorOperands.size() + << " successor operand lists" + << "\n"; + }); for (auto &op : list.successorOperands) { SuccessorOperands successorOperands = op.branch.getSuccessorOperands(op.successorIndex); // blocks that are accessed via multiple codepaths processed once if (successorOperands.size() != op.nonLiveOperands.size()) continue; + LLVM_DEBUG({ + llvm::dbgs() << "Erasing " << op.nonLiveOperands.count() + << " non-live successor operands from successor " + << op.successorIndex << " of branch: " + << OpWithFlags(op.branch, OpPrintingFlags().skipRegions()) + << "\n"; + }); // it iterates backwards because erase invalidates all successor indexes for (int i = successorOperands.size() - 1; i >= 0; --i) { if (!op.nonLiveOperands[i]) continue; + LLVM_DEBUG({ + llvm::dbgs() << " Erasing successor operand " << i << ": " + << successorOperands[i] << "\n"; + }); successorOperands.erase(i); } } + + LLVM_DEBUG({ + llvm::dbgs() << "Finished cleanup of dead values" + << "\n"; + }); } struct RemoveDeadValues : public impl::RemoveDeadValuesBase { diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp index b82d850413946..0a2a0cc1d5c73 100644 --- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp +++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp @@ -22,6 +22,7 @@ #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" @@ -870,7 +871,18 @@ LogicalResult RegionPatternRewriteDriver::simplify(bool *changed) && { ctx->executeAction( [&] { - continueRewrites = processWorklist(); + continueRewrites = false; + + // Erase unreachable blocks + // Operations like: + // %add = arith.addi %add, %add : i64 + // are legal in unreachable code. Unfortunately many patterns would be + // unsafe to apply on such IR and can lead to crashes or infinite + // loops. + continueRewrites |= + succeeded(eraseUnreachableBlocks(rewriter, region)); + + continueRewrites |= processWorklist(); // After applying patterns, make sure that the CFG of each of the // regions is kept up to date. diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp index b639e87f52744..6ee71de0f6fdb 100644 --- a/mlir/lib/Transforms/Utils/Inliner.cpp +++ b/mlir/lib/Transforms/Utils/Inliner.cpp @@ -687,7 +687,9 @@ Inliner::Impl::inlineCallsInSCC(InlinerInterfaceImpl &inlinerIface, useList.mergeUsesAfterInlining(it.targetNode, it.sourceNode); // then erase the call. - call.erase(); + const auto *callInterface = + inlinerIface.getInterfaceFor(call->getDialect()); + callInterface->eraseCall(call); // If we inlined in place, mark the node for deletion. if (inlineInPlace) { diff --git a/mlir/lib/Transforms/Utils/InliningUtils.cpp b/mlir/lib/Transforms/Utils/InliningUtils.cpp index eeb40529cc2fe..2b0a7e277aace 100644 --- a/mlir/lib/Transforms/Utils/InliningUtils.cpp +++ b/mlir/lib/Transforms/Utils/InliningUtils.cpp @@ -91,6 +91,19 @@ static void remapInlinedOperands(iterator_range inlinedBlocks, block.walk(remapOperands); } +//===----------------------------------------------------------------------===// +// DialectInlinerInterface +//===----------------------------------------------------------------------===// + +void DialectInlinerInterface::eraseCall(Operation *call) const { + call->erase(); +} + +std::tuple +DialectInlinerInterface::getInlineBlockAndPoint(Operation *call) const { + return std::make_tuple(call->getBlock(), std::next(call->getIterator())); +} + //===----------------------------------------------------------------------===// // InlinerInterface //===----------------------------------------------------------------------===// @@ -548,9 +561,11 @@ LogicalResult mlir::inlineCall( if (!interface.isLegalToInline(call, callable, shouldCloneInlinedRegion)) return cleanupState(); + auto [inlineBlock, inlinePoint] = callInterface->getInlineBlockAndPoint(call); + // Attempt to inline the call. - if (failed(inlineRegionImpl(interface, cloneCallback, src, call->getBlock(), - ++call->getIterator(), mapper, callResults, + if (failed(inlineRegionImpl(interface, cloneCallback, src, inlineBlock, + inlinePoint, mapper, callResults, callableResultTypes, call.getLoc(), shouldCloneInlinedRegion, call))) return cleanupState(); diff --git a/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp index ee5c642c943c4..baa76b9aab4e5 100644 --- a/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp +++ b/mlir/lib/Transforms/Utils/WalkPatternRewriteDriver.cpp @@ -13,11 +13,13 @@ #include "mlir/Transforms/WalkPatternRewriteDriver.h" #include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Operation.h" #include "mlir/IR/OperationSupport.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/Verifier.h" #include "mlir/IR/Visitors.h" #include "mlir/Rewrite/PatternApplicator.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -25,6 +27,26 @@ namespace mlir { +// Find all reachable blocks in the region and add them to the visitedBlocks +// set. +static void findReachableBlocks(Region ®ion, + DenseSet &reachableBlocks) { + Block *entryBlock = ®ion.front(); + reachableBlocks.insert(entryBlock); + // Traverse the CFG and add all reachable blocks to the blockList. + SmallVector worklist({entryBlock}); + while (!worklist.empty()) { + Block *block = worklist.pop_back_val(); + Operation *terminator = &block->back(); + for (Block *successor : terminator->getSuccessors()) { + if (reachableBlocks.contains(successor)) + continue; + worklist.push_back(successor); + reachableBlocks.insert(successor); + } + } +} + namespace { struct WalkAndApplyPatternsAction final : tracing::ActionImpl { @@ -88,20 +110,112 @@ void walkAndApplyPatterns(Operation *op, PatternApplicator applicator(patterns); applicator.applyDefaultCostModel(); + // Iterator on all reachable operations in the region. + // Also keep track if we visited the nested regions of the current op + // already to drive the post-order traversal. + struct RegionReachableOpIterator { + RegionReachableOpIterator(Region *region) : region(region) { + regionIt = region->begin(); + if (regionIt != region->end()) + blockIt = regionIt->begin(); + if (!llvm::hasSingleElement(*region)) + findReachableBlocks(*region, reachableBlocks); + } + // Advance the iterator to the next reachable operation. + void advance() { + assert(regionIt != region->end()); + hasVisitedRegions = false; + if (blockIt == regionIt->end()) { + ++regionIt; + while (regionIt != region->end() && + !reachableBlocks.contains(&*regionIt)) + ++regionIt; + if (regionIt != region->end()) + blockIt = regionIt->begin(); + return; + } + ++blockIt; + if (blockIt != regionIt->end()) { + LLVM_DEBUG({ + llvm::dbgs() << "Incrementing block iterator, next op: " + << OpWithFlags(&*blockIt, + OpPrintingFlags().skipRegions()) + << "\n"; + }); + } + } + // The region we're iterating over. + Region *region; + // The Block currently being iterated over. + Region::iterator regionIt; + // The Operation currently being iterated over. + Block::iterator blockIt; + // The set of blocks that are reachable in the current region. + DenseSet reachableBlocks; + // Whether we've visited the nested regions of the current op already. + bool hasVisitedRegions = false; + }; + + // Worklist of regions to visit to drive the post-order traversal. + SmallVector worklist; + + LLVM_DEBUG( + { llvm::dbgs() << "Starting walk-based pattern rewrite driver\n"; }); ctx->executeAction( [&] { + // Perform a post-order traversal of the regions, visiting each + // reachable operation. for (Region ®ion : op->getRegions()) { - region.walk([&](Operation *visitedOp) { - LLVM_DEBUG(llvm::dbgs() << "Visiting op: "; visitedOp->print( - llvm::dbgs(), OpPrintingFlags().skipRegions()); - llvm::dbgs() << "\n";); + assert(worklist.empty()); + if (region.empty()) + continue; + + // Prime the worklist with the entry block of this region. + worklist.push_back({®ion}); + while (!worklist.empty()) { + RegionReachableOpIterator &it = worklist.back(); + if (it.regionIt == it.region->end()) { + // We're done with this region. + worklist.pop_back(); + continue; + } + if (it.blockIt == it.regionIt->end()) { + // We're done with this block. + it.advance(); + continue; + } + Operation *op = &*it.blockIt; + // If we haven't visited the nested regions of this op yet, + // enqueue them. + if (!it.hasVisitedRegions) { + it.hasVisitedRegions = true; + for (Region &nestedRegion : llvm::reverse(op->getRegions())) { + if (nestedRegion.empty()) + continue; + worklist.push_back({&nestedRegion}); + } + } + // If we're not at the back of the worklist, we've enqueued some + // nested region for processing. We'll come back to this op later + // (post-order) + if (&it != &worklist.back()) + continue; + + // Preemptively increment the iterator, in case the current op + // would be erased. + it.advance(); + + LLVM_DEBUG({ + llvm::dbgs() << "Visiting op: " + << OpWithFlags(op, OpPrintingFlags().skipRegions()) + << "\n"; + }); #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS - erasedListener.visitedOp = visitedOp; + erasedListener.visitedOp = op; #endif // MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS - if (succeeded(applicator.matchAndRewrite(visitedOp, rewriter))) { - LLVM_DEBUG(llvm::dbgs() << "\tOp matched and rewritten\n";); - } - }); + if (succeeded(applicator.matchAndRewrite(op, rewriter))) + LLVM_DEBUG({ llvm::dbgs() << "\tOp matched and rewritten\n"; }); + } } }, {op}); diff --git a/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir b/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir index a89a0f4084e99..3748be74eb0f3 100644 --- a/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir +++ b/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir @@ -283,3 +283,23 @@ func.func @test_10_negative() -> (i32) { %0:2 = func.call @private_1() : () -> (i32, i32) return %0#0 : i32 } + +// ----- + +// Test that we correctly set a liveness value for operations in dead block. +// These won't be visited by the dataflow framework so the analysis need to +// explicitly manage them. +// CHECK-LABEL: test_tag: dead_block_cmpi: +// CHECK-NEXT: operand #0: not live +// CHECK-NEXT: operand #1: not live +// CHECK-NEXT: result #0: not live +func.func @dead_block() { + %false = arith.constant false + %zero = arith.constant 0 : i64 + cf.cond_br %false, ^bb1, ^bb4 + ^bb1: + %3 = arith.cmpi eq, %zero, %zero {tag = "dead_block_cmpi"} : i64 + cf.br ^bb1 + ^bb4: + return +} diff --git a/mlir/test/Dialect/Affine/slicing-utils.mlir b/mlir/test/Dialect/Affine/slicing-utils.mlir index 0848a924b9d96..c53667a98cfbe 100644 --- a/mlir/test/Dialect/Affine/slicing-utils.mlir +++ b/mlir/test/Dialect/Affine/slicing-utils.mlir @@ -292,3 +292,26 @@ func.func @slicing_test_multiple_return(%arg0: index) -> (index, index) { %0:2 = "slicing-test-op"(%arg0, %arg0): (index, index) -> (index, index) return %0#0, %0#1 : index, index } + +// ----- + +// FWD-LABEL: graph_region_with_cycle +// BWD-LABEL: graph_region_with_cycle +// FWDBWD-LABEL: graph_region_with_cycle +func.func @graph_region_with_cycle() { + test.isolated_graph_region { + // FWD: matched: [[V0:%.+]] = "slicing-test-op"([[V1:%.+]]) : (i1) -> i1 forward static slice: + // FWD: [[V1]] = "slicing-test-op"([[V0]]) : (i1) -> i1 + // FWD: matched: [[V1]] = "slicing-test-op"([[V0]]) : (i1) -> i1 forward static slice: + // FWD: [[V0]] = "slicing-test-op"([[V1]]) : (i1) -> i1 + + // BWD: matched: [[V0:%.+]] = "slicing-test-op"([[V1:%.+]]) : (i1) -> i1 backward static slice: + // BWD: [[V1]] = "slicing-test-op"([[V0]]) : (i1) -> i1 + // BWD: matched: [[V1]] = "slicing-test-op"([[V0]]) : (i1) -> i1 backward static slice: + // BWD: [[V0]] = "slicing-test-op"([[V1]]) : (i1) -> i1 + %0 = "slicing-test-op"(%1) : (i1) -> i1 + %1 = "slicing-test-op"(%0) : (i1) -> i1 + } + + return +} diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir index 3d5a46d13e59d..cf570beb14b9e 100644 --- a/mlir/test/Dialect/Arith/canonicalize.mlir +++ b/mlir/test/Dialect/Arith/canonicalize.mlir @@ -3363,3 +3363,18 @@ func.func @bf16_fma(%arg0: vector<32x32x32xbf16>, %arg1: vector<32x32x32xbf16>, } } #-} + +// CHECK-LABEL: func @unreachable() +// CHECK-NEXT: return +// CHECK-NOT: arith +func.func @unreachable() { + return +^unreachable: + %c1_i64 = arith.constant 1 : i64 + // This self referencing operation is legal in an unreachable block. + // Many patterns are unsafe with respect to this kind of situation, + // check that we don't infinite loop here. + %add = arith.addi %add, %c1_i64 : i64 + cf.br ^unreachable +} + diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir index 2efb5893c8511..eb0093106dc11 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir @@ -810,3 +810,59 @@ module @inner_module { return %t : tensor<5xf32> } } + +// ----- + +// CHECK: func.func @custom_types( +// CHECK-SAME: %[[arg:.*]]: !test.test_memref<[4, 4], f64> +// CHECK-SAME: ) -> (!test.test_memref<[4, 8], f64>, +// CHECK-SAME: !test.test_memref<[4, 8], f64>) +func.func @custom_types(%arg: !test.test_tensor<[4, 4], f64>) + -> (!test.test_tensor<[4, 8], f64>, !test.test_tensor<[4, 8], f64>) { + // CHECK: %[[out1:.*]] = "test.dummy_memref_op"(%[[arg]]) : + // CHECK-SAME: (!test.test_memref<[4, 4], f64>) -> !test.test_memref<[4, 8], f64> + %out1 = "test.dummy_tensor_op"(%arg) : (!test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 8], f64> + + // CHECK: %[[alloc:.*]] = "test.create_memref_op" + // CHECK: %[[out2:.*]] = "test.dummy_memref_op"(%[[alloc]]) + // CHECK-SAME: (!test.test_memref<[4, 4], f64>) -> !test.test_memref<[4, 8], f64> + %alloc = "test.create_tensor_op"() : () -> !test.test_tensor<[4, 4], f64> + %out2 = "test.dummy_tensor_op"(%alloc) : (!test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 8], f64> + + // CHECK: return %[[out1]], %[[out2]] + return %out1, %out2 : + !test.test_tensor<[4, 8], f64>, !test.test_tensor<[4, 8], f64> +} + +// ----- + +// CHECK: func.func @custom_types_foo( +// CHECK-SAME: %[[arg:.*]]: !test.test_memref<[4, 4], f64> +// CHECK-SAME: ) -> !test.test_memref<[4, 4], f64> +func.func @custom_types_foo(%arg: !test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 4], f64> { + // CHECK: %[[out:.*]] = "test.dummy_memref_op"(%[[arg]]) + %out = "test.dummy_tensor_op"(%arg) : (!test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 4], f64> + // CHECK: return %[[out]] + return %out : !test.test_tensor<[4, 4], f64> +} + +// CHECK: func.func @custom_types_bar( +// CHECK-SAME: %[[arg:.*]]: !test.test_memref<[4, 4], f64> +// CHECK-SAME: ) -> !test.test_memref<[4, 8], f64> +func.func @custom_types_bar(%arg: !test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 8], f64> { + // CHECK: %[[call:.*]] = call @custom_types_foo(%[[arg]]) + %call = func.call @custom_types_foo(%arg) : (!test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 4], f64> + + // CHECK: %[[out:.*]] = "test.dummy_memref_op"(%[[call]]) + %out = "test.dummy_tensor_op"(%call) : (!test.test_tensor<[4, 4], f64>) + -> !test.test_tensor<[4, 8], f64> + + // CHECK: return %[[out]] + return %out : !test.test_tensor<[4, 8], f64> +} diff --git a/mlir/test/Dialect/Bufferization/invalid.mlir b/mlir/test/Dialect/Bufferization/invalid.mlir index 2c8807b66de74..9884b040119d0 100644 --- a/mlir/test/Dialect/Bufferization/invalid.mlir +++ b/mlir/test/Dialect/Bufferization/invalid.mlir @@ -127,3 +127,63 @@ func.func @invalid_manual_deallocation() { // expected-error @below{{op attribute 'bufferization.manual_deallocation' can be used only on ops that have an allocation and/or free side effect}} arith.constant {bufferization.manual_deallocation} 0 : index } + +// ----- + +func.func @invalid_rank_to_buffer(%t: tensor<1x2x3x4xf32>) { + // expected-error @below{{'bufferization.to_buffer' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{shapes do not match}} + %b = bufferization.to_buffer %t + : tensor<1x2x3x4xf32> to memref<1x2x3xf32> + return +} + +// ----- + +func.func @invalid_rank_to_tensor(%b: memref<1x2x3xf32>) { + // expected-error @below{{'bufferization.to_tensor' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{shapes do not match}} + %t = bufferization.to_tensor %b + : memref<1x2x3xf32> to tensor<1x2x3x4xf32> + return +} + +// ----- + +func.func @invalid_shape_to_buffer(%t: tensor<1x2x3x4xf32>) { + // expected-error @below{{'bufferization.to_buffer' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{shapes do not match}} + %b = bufferization.to_buffer %t + : tensor<1x2x3x4xf32> to memref<1x2x4x3xf32> + return +} + +// ----- + +func.func @invalid_shape_to_tensor(%b: memref<1x2x4x3xf32>) { + // expected-error @below{{'bufferization.to_tensor' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{shapes do not match}} + %t = bufferization.to_tensor %b + : memref<1x2x4x3xf32> to tensor<1x2x3x4xf32> + return +} + +// ----- + +func.func @invalid_type_to_buffer(%t: tensor<1x2x3x4xf32>) { + // expected-error @below{{'bufferization.to_buffer' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{element types do not match}} + %b = bufferization.to_buffer %t + : tensor<1x2x3x4xf32> to memref<1x2x3x4xf16> + return +} + +// ----- + +func.func @invalid_type_to_tensor(%b: memref<1x2x3x4xf16>) { + // expected-error @below{{'bufferization.to_tensor' op failed to verify that specified tensor and buffer types match}} + // expected-error @below{{element types do not match}} + %t2 = bufferization.to_tensor %b + : memref<1x2x3x4xf16> to tensor<1x2x3x4xf32> + return +} diff --git a/mlir/test/Dialect/Bufferization/ops.mlir b/mlir/test/Dialect/Bufferization/ops.mlir index fc6df4a09f706..b0db1bb2d0389 100644 --- a/mlir/test/Dialect/Bufferization/ops.mlir +++ b/mlir/test/Dialect/Bufferization/ops.mlir @@ -83,3 +83,40 @@ func.func @test_dealloc_op(%arg0: memref<2xf32>, %arg1: memref<4xi32>, bufferization.dealloc return %0#0, %0#1 : i1, i1 } + +// CHECK: func.func @test_builtin_custom_builtin_type_conversion +// CHECK-SAME: (%[[t:.*]]: tensor<42xf32>) -> tensor<42xf32> +func.func @test_builtin_custom_builtin_type_conversion(%t: tensor<42xf32>) + -> tensor<42xf32> { + // CHECK: %[[buffer:.*]] = bufferization.to_buffer %[[t]] + // CHECK-SAME: to !test.test_memref<[42], f32> + %buffer = bufferization.to_buffer %t + : tensor<42xf32> to !test.test_memref<[42], f32> + + // CHECK: %[[tensor:.*]] = bufferization.to_tensor %[[buffer]] + // CHECK-SAME: to tensor<42xf32> + %tensor = bufferization.to_tensor %buffer + : !test.test_memref<[42], f32> to tensor<42xf32> + + // CHECK: return %[[tensor]] + return %tensor : tensor<42xf32> +} + +// CHECK: func.func @test_custom_builtin_custom_type_conversion +// CHECK-SAME: (%[[t:.*]]: !test.test_tensor<[42], f32>) +// CHECK-SAME: -> !test.test_tensor<[42], f32> +func.func @test_custom_builtin_custom_type_conversion(%t: !test.test_tensor<[42], f32>) + -> !test.test_tensor<[42], f32> { + // CHECK: %[[buffer:.*]] = bufferization.to_buffer %[[t]] + // CHECK-SAME: to memref<42xf32> + %buffer = bufferization.to_buffer %t + : !test.test_tensor<[42], f32> to memref<42xf32> + + // CHECK: %[[tensor:.*]] = bufferization.to_tensor %[[buffer]] + // CHECK-SAME: to !test.test_tensor<[42], f32> + %tensor = bufferization.to_tensor %buffer + : memref<42xf32> to !test.test_tensor<[42], f32> + + // CHECK: return %[[tensor]] + return %tensor : !test.test_tensor<[42], f32> +} diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir index 193ab7987a2b6..19a65be62dc92 100644 --- a/mlir/test/Dialect/LLVMIR/global.mlir +++ b/mlir/test/Dialect/LLVMIR/global.mlir @@ -132,7 +132,7 @@ llvm.mlir.global internal constant @constant(37.0) : !llvm.label // ----- func.func @foo() { - // expected-error @+1 {{op symbol's parent must have the SymbolTable trait}} + // expected-error @+1 {{must appear at the module level}} llvm.mlir.global internal @bar(42) : i32 return diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index bd1106e304c60..62cb562e513e8 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -99,20 +99,6 @@ func.func @alloca_non_integer_alignment() { // ----- -func.func @gep_missing_input_result_type(%pos : i64, %base : !llvm.ptr) { - // expected-error@+1 {{number of operands and types do not match: got 2 operands and 0 types}} - llvm.getelementptr %base[%pos] : () -> (), i64 -} - -// ----- - -func.func @gep_missing_input_type(%pos : i64, %base : !llvm.ptr) { - // expected-error@+1 {{number of operands and types do not match: got 2 operands and 0 types}} - llvm.getelementptr %base[%pos] : () -> (!llvm.ptr), i64 -} - -// ----- - func.func @gep_missing_result_type(%pos : i64, %base : !llvm.ptr) { // expected-error@+1 {{op requires one result}} llvm.getelementptr %base[%pos] : (!llvm.ptr, i64) -> (), i64 diff --git a/mlir/test/Dialect/Linalg/transform-op-replace.mlir b/mlir/test/Dialect/Linalg/transform-op-replace.mlir index 1a40912977dec..2801522e81ac2 100644 --- a/mlir/test/Dialect/Linalg/transform-op-replace.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-replace.mlir @@ -12,10 +12,8 @@ module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op transform.structured.replace %0 { - builtin.module { - func.func @foo() { - "dummy_op"() : () -> () - } + func.func @foo() { + "dummy_op"() : () -> () } } : (!transform.any_op) -> !transform.any_op transform.yield diff --git a/mlir/test/Dialect/Mesh/simplifications.mlir b/mlir/test/Dialect/Mesh/simplifications.mlir index 2540fbf9510c4..e955f4c134259 100644 --- a/mlir/test/Dialect/Mesh/simplifications.mlir +++ b/mlir/test/Dialect/Mesh/simplifications.mlir @@ -165,3 +165,15 @@ func.func @all_reduce_arith_minsi_endomorphism( // CHECK: return %[[ALL_REDUCE_RES]] return %2 : tensor<5xi32> } + +// Ensure this case without endomorphism op not crash. +// CHECK-LABEL: func.func @no_endomorphism_op +func.func @no_endomorphism_op(%arg0: tensor<2xi64>) -> i64 { + %c0 = arith.constant 0 : index + %c1_i64 = arith.constant 1 : i64 + // CHECK: tensor.extract + %extracted = tensor.extract %arg0[%c0] : tensor<2xi64> + // CHECK: arith.maxsi + %0 = arith.maxsi %extracted, %c1_i64 : i64 + return %0 : i64 +} diff --git a/mlir/test/Dialect/Quant/Bytecode/types.mlir b/mlir/test/Dialect/Quant/Bytecode/types.mlir index 8c79b757eeb19..09a8bb902fd87 100644 --- a/mlir/test/Dialect/Quant/Bytecode/types.mlir +++ b/mlir/test/Dialect/Quant/Bytecode/types.mlir @@ -73,3 +73,19 @@ module @parseUniformSubChannel attributes { // CHECK: !quant.uniform bytecode.test = !quant.uniform } {} + +//===----------------------------------------------------------------------===// +// QuantileType +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: parseQuantileNoStorageBounds +module @parseQuantileNoStorageBounds attributes { + // CHECK: !quant.quantile + bytecode.test = !quant.quantile +} {} + +// CHECK-LABEL: parseQuantileWithStorageBounds +module @parseQuantileWithStorageBounds attributes { + // CHECK: !quant.quantile> + bytecode.test = !quant.quantile> +} {} diff --git a/mlir/test/Dialect/Quant/invalid-quantile-types.mlir b/mlir/test/Dialect/Quant/invalid-quantile-types.mlir new file mode 100644 index 0000000000000..4a7703fd0e553 --- /dev/null +++ b/mlir/test/Dialect/Quant/invalid-quantile-types.mlir @@ -0,0 +1,42 @@ +// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics + +//===----------------------------------------------------------------------===// +// Verify errors (caught by verify(), reached through getChecked()) +//===----------------------------------------------------------------------===// + +// Storage type must be an integer or float. +// expected-error @+1 {{storage type must be an integer or float type}} +func.func private @invalid_storage_type() -> !quant.quantile:f32, {1.0}> + +// ----- + +// Quantile (expressed) type must be a float. +// expected-error @+1 {{quantile type must be a float or integer type}} +func.func private @invalid_quantile_type() -> !quant.quantile, {1.0, 0.0, -1.0}> + +// ----- + +// Quantile LUT must not be empty. +// expected-error @+1 {{quantile values must not be empty}} +func.func private @empty_quantiles() -> !quant.quantile + +// ----- + +// LUT size must match the number of representable storage values. +// ui4 has 16 representable values [0,15], but only 3 are provided. +// expected-error @+1 {{quantile LUT size (3) must equal the number of representable storage values (16)}} +func.func private @wrong_lut_size() -> !quant.quantile + +// ----- + +// Explicit storage range: min must be strictly less than max. +// si4 default range is [-8,7]; explicit 5:3 has min > max. +// expected-error @+1 {{storage min must be less than storage max}} +func.func private @invalid_range_order() -> !quant.quantile> + +// ----- + +// LUT size must match the total representable values of the storage type. +// f4E2M1FN has 16 representable values regardless of explicit range, but only 3 are provided. +// expected-error @+1 {{quantile LUT size (3) must equal the number of representable storage values (13)}} +func.func private @wrong_lut_size_with_range() -> !quant.quantile> diff --git a/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir b/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir index 3b358443e43f2..da1fac1339019 100644 --- a/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir +++ b/mlir/test/Dialect/Quant/parse-uniform-invalid.mlir @@ -80,6 +80,36 @@ // expected-error@+1 {{illegal storage type minimum: -9}} !qalias = !quant.uniform:f32, 0.99872:127> +// ----- +// Illegal storage min/max: max > defaultMax +// expected-error@+1 {{illegal storage type maximum: 60000}} +!qalias = !quant.uniform:f32, 0.99872:127> + +// ----- +// Illegal storage min/max: min < defaultMin +// expected-error@+1 {{illegal storage type minimum: -60000}} +!qalias = !quant.uniform:f32, 0.99872:127> + +// ----- +// Illegal storage min/max: max > defaultMax +// expected-error@+1 {{illegal storage type maximum: 500}} +!qalias = !quant.uniform:f32, 0.99872:127> + +// ----- +// Illegal storage min/max: min < defaultMin +// expected-error@+1 {{illegal storage type minimum: -500}} +!qalias = !quant.uniform:f32, 0.99872:127> + +// ----- +// Illegal storage min/max: max > defaultMax +// expected-error@+1 {{illegal storage type maximum: 10}} +!qalias = !quant.uniform:f32, 0.99872:127> + +// ----- +// Illegal storage min/max: min < defaultMin +// expected-error@+1 {{illegal storage type minimum: -10}} +!qalias = !quant.uniform:f32, 0.99872:127> + // ----- // Illegal uniform params: invalid scale // expected-error@+1 {{expected floating point literal}} @@ -105,11 +135,6 @@ // expected-error@+1 {{expected non-function type}} !qalias = !quant.uniform:f33, 0.99872:127> -// ----- -// Illegal scale: negative -// expected-error@+1 {{scale -1.000000e+00 out of expressed type range}} -!qalias = !quant.uniform:f32, -1.0:127> - // ----- // Illegal uniform params: missing quantized dimension // expected-error@+1 {{expected integer value}} @@ -126,26 +151,26 @@ // expected-error@+1 {{illegal quantized dimension: -1}} !qalias = !quant.uniform -// ----- -// Scale f16 underflow -// expected-error@+1 {{scale 5.800000e-08 out of expressed type range}} -!qalias = !quant.uniform - // ----- // Scale f16 overflow // expected-error@+1 {{scale 6.600000e+04 out of expressed type range}} !qalias = !quant.uniform // ----- -// Scale f16 underflow in per-axis quantization -// expected-error@+1 {{scale 5.800000e-08 out of expressed type range}} -!qalias = !quant.uniform +// Scale f16 negative overflow +// expected-error@+1 {{scale -6.600000e+04 out of expressed type range}} +!qalias = !quant.uniform // ----- // Scale f16 overflow in per-axis quantization // expected-error@+1 {{scale 6.600000e+04 out of expressed type range}} !qalias = !quant.uniform +// ----- +// Scale f16 negative overflow in per-axis quantization +// expected-error@+1 {{scale -6.600000e+04 out of expressed type range}} +!qalias = !quant.uniform + // ----- // Illegal negative axis in sub-channel quantization // expected-error@+1 {{illegal quantized dimension: -1}} @@ -233,5 +258,23 @@ // Scale out of expressed type range in sub-channel quantization // expected-error@+2 {{scale 6.600000e+04 out of expressed type range}} !qalias = !quant.uniform + {{6.6e4:120,9.987200e-01:127}, {2.000000e+02:255,9.987200e-01}}> + + +// ----- + +// Invalid LUT size: 16 values but explicit range 6:10 has only 5 representable values. +// expected-error@+1 {{quantile LUT size (16) must equal the number of representable storage values (5)}} +!qalias = !quant.uniform>:f32, 0.99872:127> + +// ----- + +// Quantile storage range: min must be strictly less than max. +// expected-error@+1 {{storage min must be less than storage max}} +!qalias = !quant.uniform>:f32, 0.99872:127> + +// ----- +// Quantile LUT size (3) does not match the 16 representable values of f4E2M1FN's default range. +// expected-error@+1 {{quantile LUT size (3) must equal the number of representable storage values (16)}} +!qalias = !quant.uniform:f32, 0.99872:127> diff --git a/mlir/test/Dialect/Quant/parse-uniform.mlir b/mlir/test/Dialect/Quant/parse-uniform.mlir index 80a6621ed6979..b674184772947 100644 --- a/mlir/test/Dialect/Quant/parse-uniform.mlir +++ b/mlir/test/Dialect/Quant/parse-uniform.mlir @@ -19,6 +19,42 @@ func.func @parse() -> !qalias { return %0 : !qalias } +// ----- +// Default min/max value optimization for integers. +// CHECK: !quant.uniform +!qalias = !quant.uniform:f32, 0.99872:127 > +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Default min/max value optimization for f8E5M2. +// CHECK: !quant.uniform +!qalias = !quant.uniform:f32, 0.99872:127 > +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Default min/max value optimization for f8E4M3FN. +// CHECK: !quant.uniform +!qalias = !quant.uniform:f32, 0.99872:127 > +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Default min/max value optimization for f4E2M1FN. +// CHECK: !quant.uniform +!qalias = !quant.uniform:f32, 0.99872:127 > +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + // ----- // Required per-layer params specified: // [unsigned] storageType, expressedType, scale @@ -47,6 +83,33 @@ func.func @parse() -> !qalias { return %0 : !qalias } +// ----- +// Storage type: f8E5M2 +// CHECK: !quant.uniform +!qalias = !quant.uniform +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Storage type: f8E4M3FN +// CHECK: !quant.uniform +!qalias = !quant.uniform +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Storage type: f4E2M1FN +// CHECK: !quant.uniform +!qalias = !quant.uniform +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + // ----- // Storage type: i16 // CHECK: !quant.uniform @@ -172,3 +235,40 @@ func.func @parse() -> !qalias { %0 = "foo"() : () -> !qalias return %0 : !qalias } + +// ----- +// Negative scale checking +// CHECK: !quant.uniform +!qalias = !quant.uniform +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Per axis negative scale checking +// CHECK: !quant.uniform +!qalias = !quant.uniform +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Storage type: QuantileType with narrowed explicit range `-6:6` (13 representable values). +// CHECK: !quant.uniform>:f32, 9.987200e-01:127> +!qalias = !quant.uniform>:f32, 0.99872:127> +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + +// ----- +// Storage type: QuantileType +// CHECK: !quant.uniform:f32, 2.0e+2 > +func.func @parse() -> !qalias { + %0 = "foo"() : () -> !qalias + return %0 : !qalias +} + diff --git a/mlir/test/Dialect/Quant/quantile-types.mlir b/mlir/test/Dialect/Quant/quantile-types.mlir new file mode 100644 index 0000000000000..c8840a7b3d3f2 --- /dev/null +++ b/mlir/test/Dialect/Quant/quantile-types.mlir @@ -0,0 +1,76 @@ +// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file | FileCheck %s + +// ----- +// Quantile type: ui4 storage-type with f16 expressed-type, 16 entries (default range 0..15). +// CHECK-LABEL: func private @quantile_ui4_f16 +// CHECK-SAME: !quant.quantile) -> () + +// ----- +// Quantile type: si8 storage-type with f32 expressed-type, explicit range -2:2 (5 entries). +// CHECK: func private @quantile_si8_f32(!quant.quantile>) +func.func private @quantile_si8_f32(!quant.quantile>) -> () + +// ----- +// Quantile type: i8 (signless) storage-type with f32 expressed-type, explicit range -1:1 (3 entries). +// CHECK: func private @quantile_i8_f32(!quant.quantile>) +func.func private @quantile_i8_f32(!quant.quantile>) -> () + +// ----- +// Quantile type: f8E4M3FN float storage-type with f32 expressed-type, explicit range -1:1 (3 entries). +// CHECK: func private @quantile_f8_f32(!quant.quantile>) +func.func private @quantile_f8_f32(!quant.quantile>) -> () + +// ----- +// Quantile type: ui4 storage-type with bf16 expressed-type, 16 entries. +// CHECK-LABEL: func private @quantile_ui4_bf16 +// CHECK-SAME: !quant.quantile) -> () + +// ----- +// Quantile type used as a return type. +// CHECK-LABEL: func private @quantile_as_return +// CHECK-SAME: !quant.quantile !quant.quantile + +// ----- +// NF4-style 16-entry quantile table. +// CHECK-LABEL: @nf4_16_values +// CHECK-SAME: !quant.quantile) -> () + +// ----- +// Explicit storage min/max range (unsigned storage, narrowed range 0..7, 8 entries). +// CHECK: func private @quantile_with_range(!quant.quantile>) +func.func private @quantile_with_range(!quant.quantile>) -> () + +// ----- +// Explicit range is preserved through round-trip. +// CHECK: func private @quantile_signed_range(!quant.quantile>) +func.func private @quantile_signed_range(!quant.quantile>) -> () + +// ----- +// Signed 4-bit storage-type uses full 16-entry LUT (range -8..7). +// CHECK-LABEL: func private @quantile_negatives +// CHECK-SAME: !quant.quantile +func.func private @quantile_negatives(!quant.quantile) -> () + +// ----- +// 1-bit unsigned storage: minimal 2-entry LUT. +// CHECK: func private @quantile_ui1_f16(!quant.quantile) +func.func private @quantile_ui1_f16(!quant.quantile) -> () + +// ----- +// LUT values in descending order (ui4, explicit range 0:7, 8 entries). +// CHECK: func private @quantile_descending(!quant.quantile>) +func.func private @quantile_descending(!quant.quantile>) -> () + +// ----- +// LUT values in arbitrary order (ui4, explicit range 0:7, 8 entries). +// CHECK: func private @quantile_random_order(!quant.quantile>) +func.func private @quantile_random_order(!quant.quantile>) -> () diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir index 8ba8013d008a0..b15fabdd29c61 100644 --- a/mlir/test/Dialect/SCF/canonicalize.mlir +++ b/mlir/test/Dialect/SCF/canonicalize.mlir @@ -1925,3 +1925,16 @@ func.func @index_switch_fold_no_res() { // CHECK-LABEL: func.func @index_switch_fold_no_res() // CHECK-NEXT: "test.op"() : () -> () + +// ----- + +// CHECK-LABEL: func @scf_for_all_step_size_0() +// CHECK: scf.forall (%{{.*}}) = (0) to (1) step (0) +func.func @scf_for_all_step_size_0() { + %x = arith.constant 0 : index + scf.forall (%i, %j) = (0, 4) to (1, 5) step (%x, 8) { + vector.print %x : index + scf.forall.in_parallel {} + } + return +} diff --git a/mlir/test/Dialect/SparseTensor/scf_1_N_conversion.mlir b/mlir/test/Dialect/SparseTensor/scf_1_N_conversion.mlir index f5d6a08b7de31..515de5502f322 100644 --- a/mlir/test/Dialect/SparseTensor/scf_1_N_conversion.mlir +++ b/mlir/test/Dialect/SparseTensor/scf_1_N_conversion.mlir @@ -86,3 +86,47 @@ func.func @while(%arg0: tensor<1024xf32, #SparseVector>, %c: i1) -> tensor<1024x } return %0: tensor<1024xf32, #SparseVector> } + +// CHECK-LABEL: func.func @index_switch( +// CHECK-SAME: %[[PRED:.*0]]: index, +// CHECK-SAME: %[[VAL_A_1:.*1]]: memref, +// CHECK-SAME: %[[VAL_A_2:.*2]]: memref, +// CHECK-SAME: %[[VAL_A_3:.*3]]: memref, +// CHECK-SAME: %[[VAL_A_4:.*4]]: !sparse_tensor.storage_specifier +// CHECK-SAME: %[[VAL_B_1:.*5]]: memref, +// CHECK-SAME: %[[VAL_B_2:.*6]]: memref, +// CHECK-SAME: %[[VAL_B_3:.*7]]: memref, +// CHECK-SAME: %[[VAL_B_4:.*8]]: !sparse_tensor.storage_specifier +// CHECK-SAME: %[[VAL_C_1:.*9]]: memref, +// CHECK-SAME: %[[VAL_C_2:.*10]]: memref, +// CHECK-SAME: %[[VAL_C_3:.*11]]: memref, +// CHECK-SAME: %[[VAL_C_4:.*12]]: !sparse_tensor.storage_specifier + +// CHECK: %[[RES:.*]]:4 = scf.index_switch %[[PRED]] +// CHECK-SAME: -> memref, memref, memref, !sparse_tensor.storage_specifier +// CHECK: case 1 { +// CHECK: scf.yield %[[VAL_A_1]], %[[VAL_A_2]], %[[VAL_A_3]], %[[VAL_A_4]] +// CHECK: case 2 { +// CHECK: scf.yield %[[VAL_B_1]], %[[VAL_B_2]], %[[VAL_B_3]], %[[VAL_B_4]] +// CHECK: default { +// CHECK: scf.yield %[[VAL_C_1]], %[[VAL_C_2]], %[[VAL_C_3]], %[[VAL_C_4]] + +// CHECK: return %[[RES]]#0, %[[RES]]#1, %[[RES]]#2, %[[RES]]#3 : +// CHECK-SAME: memref, memref, memref, !sparse_tensor.storage_specifier + +func.func @index_switch(%pred: index, %a: tensor<5xf32, #SparseVector>, + %b: tensor<5xf32, #SparseVector>, + %c: tensor<5xf32, #SparseVector>) -> tensor<5xf32, #SparseVector> { + %0 = scf.index_switch %pred -> tensor<5xf32, #SparseVector> + case 1 { + scf.yield %a : tensor<5xf32, #SparseVector> + } + case 2 { + scf.yield %b : tensor<5xf32, #SparseVector> + } + default { + scf.yield %c : tensor<5xf32, #SparseVector> + } + + return %0 : tensor<5xf32, #SparseVector> +} diff --git a/mlir/test/Dialect/Transform/ops-invalid.mlir b/mlir/test/Dialect/Transform/ops-invalid.mlir index 71a260f1196e9..1e2f7ad69ab8b 100644 --- a/mlir/test/Dialect/Transform/ops-invalid.mlir +++ b/mlir/test/Dialect/Transform/ops-invalid.mlir @@ -482,9 +482,10 @@ module { // ----- module attributes { transform.with_named_sequence} { + // expected-note @below {{ancestor transform op}} transform.sequence failures(suppress) { ^bb0(%arg0: !transform.any_op): - // expected-error @below {{op symbol's parent must have the SymbolTable trai}} + // expected-error @below {{cannot be defined inside another transform op}} transform.named_sequence @nested() { transform.yield } diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir index 12187dd18012b..ea2343efd246e 100644 --- a/mlir/test/Dialect/Vector/canonicalize.mlir +++ b/mlir/test/Dialect/Vector/canonicalize.mlir @@ -1379,6 +1379,21 @@ func.func @extract_strided_broadcast4(%arg0: f32) -> vector<1x4xf32> { // ----- +// Check the case where the same dimension is both broadcasted and sliced +// CHECK-LABEL: func @extract_strided_broadcast5 +// CHECK-SAME: (%[[ARG:.+]]: vector<2x1xf32>) +// CHECK: %[[V:.+]] = vector.broadcast %[[ARG]] : vector<2x1xf32> to vector<2x4xf32> +// CHECK: return %[[V]] +func.func @extract_strided_broadcast5(%arg0: vector<2x1xf32>) -> vector<2x4xf32> { + %0 = vector.broadcast %arg0 : vector<2x1xf32> to vector<2x8xf32> + %1 = vector.extract_strided_slice %0 + {offsets = [0, 4], sizes = [2, 4], strides = [1, 1]} + : vector<2x8xf32> to vector<2x4xf32> + return %1 : vector<2x4xf32> +} + +// ----- + // CHECK-LABEL: consecutive_shape_cast // CHECK: %[[C:.*]] = vector.shape_cast %{{.*}} : vector<16xf16> to vector<4x4xf16> // CHECK-NEXT: return %[[C]] : vector<4x4xf16> diff --git a/mlir/test/IR/invalid-func-op.mlir b/mlir/test/IR/invalid-func-op.mlir index 8fd7af22e9598..d995689ebb8d0 100644 --- a/mlir/test/IR/invalid-func-op.mlir +++ b/mlir/test/IR/invalid-func-op.mlir @@ -31,7 +31,7 @@ func.func @func_op() { // ----- func.func @func_op() { - // expected-error@+1 {{op symbol's parent must have the SymbolTable trait}} + // expected-error@+1 {{entry block must have 1 arguments to match function signature}} func.func @mixed_named_arguments(f32) { ^entry: return @@ -42,7 +42,7 @@ func.func @func_op() { // ----- func.func @func_op() { - // expected-error@+1 {{op symbol's parent must have the SymbolTable trait}} + // expected-error@+1 {{type of entry block argument #0('i32') must match the type of the corresponding argument in function signature('f32')}} func.func @mixed_named_arguments(f32) { ^entry(%arg : i32): return diff --git a/mlir/test/IR/invalid.mlir b/mlir/test/IR/invalid.mlir index d0bbf8669b63d..d4a035654d34a 100644 --- a/mlir/test/IR/invalid.mlir +++ b/mlir/test/IR/invalid.mlir @@ -699,3 +699,19 @@ func.func @drop_references_on_block_parse_error(){ }) : () -> () return } + +// ----- + +func.func @foo() { + cf.br ^bb2 + + ^bb1: + // expected-error@+1 {{forward reference of value '%1' requires explicit type specification}} + test.format_operand_optional_type_op %0, %1 + return + + ^bb2: + %0 = arith.constant 0 : i64 + %1 = memref.alloc() : memref<1xf64> + cf.br ^bb1 +} diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir index 3bb6e38b4d613..a99f1cab01354 100644 --- a/mlir/test/IR/parser.mlir +++ b/mlir/test/IR/parser.mlir @@ -1484,3 +1484,13 @@ test.dialect_custom_format_fallback custom_format_fallback // Check that an op with an optional result parses f80 as type. // CHECK: test.format_optional_result_d_op : f80 test.format_optional_result_d_op : f80 + +// Can skip type definition for operands, if they are already defined in the same block +// CHECK-LABEL: func @optional_operand_types +func.func @optional_operand_types(%arg0: i64, %arg1: memref<1xf64>) { + // CHECK: test.format_operand_optional_type_op %arg0, %arg1 + test.format_operand_optional_type_op %arg0, %arg1 + // CHECK: test.format_operand_optional_type_op %arg0, %arg1 + test.format_operand_optional_type_op %arg0, %arg1 : memref<1xf64> + return +} diff --git a/mlir/test/IR/recursive-distinct-attr.mlir b/mlir/test/IR/recursive-distinct-attr.mlir new file mode 100644 index 0000000000000..5afb5c59e0fcf --- /dev/null +++ b/mlir/test/IR/recursive-distinct-attr.mlir @@ -0,0 +1,13 @@ +// RUN: mlir-opt -emit-bytecode %s | mlir-opt --mlir-print-debuginfo | FileCheck %s + +// Verify that the distinct attribute which is used transitively +// through two aliases does not end up duplicated when round-tripped +// through bytecode. + +// CHECK: distinct[0] +// CHECK-NOT: distinct[1] +#attr_ugly = #test end> +#attr_ugly1 = #test + +module attributes {test.alias = #attr_ugly, test.alias1 = #attr_ugly1} { +} \ No newline at end of file diff --git a/mlir/test/IR/region.mlir b/mlir/test/IR/region.mlir index e2088817c5204..58e410af41c72 100644 --- a/mlir/test/IR/region.mlir +++ b/mlir/test/IR/region.mlir @@ -87,17 +87,18 @@ func.func @named_region_has_wrong_number_of_blocks() { // CHECK: test.single_no_terminator_op "test.single_no_terminator_op"() ( { - %foo = arith.constant 1 : i32 + func.func @foo1() { return } + func.func @foo2() { return } } ) : () -> () // CHECK: test.variadic_no_terminator_op "test.variadic_no_terminator_op"() ( { - %foo = arith.constant 1 : i32 + func.func @foo1() { return } }, { - %bar = arith.constant 1 : i32 + func.func @foo2() { return } } ) : () -> () diff --git a/mlir/test/IR/test-clone.mlir b/mlir/test/IR/test-clone.mlir index 0c07593aef32d..f723efc1a2c53 100644 --- a/mlir/test/IR/test-clone.mlir +++ b/mlir/test/IR/test-clone.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(test-clone))" | FileCheck %s +// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(test-clone))" --split-input-file | FileCheck %s module { func.func @fixpoint(%arg1 : i32) -> i32 { @@ -18,7 +18,8 @@ module { // CHECK-NEXT: notifyOperationInserted: test.yield // CHECK-NEXT: notifyOperationInserted: func.return -// CHECK: func @fixpoint(%[[arg0:.+]]: i32) -> i32 { +// CHECK-LABEL: func @fixpoint +// CHECK-SAME: (%[[arg0:.+]]: i32) -> i32 { // CHECK-NEXT: %[[i0:.+]] = "test.use"(%[[arg0]]) ({ // CHECK-NEXT: %[[r2:.+]] = "test.use2"(%[[arg0]]) ({ // CHECK-NEXT: "test.yield2"(%[[arg0]]) : (i32) -> () @@ -33,3 +34,33 @@ module { // CHECK-NEXT: }) : (i32) -> i32 // CHECK-NEXT: return %[[i1]] : i32 // CHECK-NEXT: } + +// ----- + +func.func @clone_unregistered_with_attrs() { + "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = 3.14 : f32}> : () -> () + "unregistered.bar"() : () -> () + "unregistered.empty_dict"() <{}> : () -> () + "unregistered.complex"() <{ + array = [1, 2, 3], + dict = {key1 = 42 : i32, key2 = "value"}, + nested = {inner = {deep = 100 : i64}} + }> : () -> () + return +} + +// CHECK: notifyOperationInserted: unregistered.foo +// CHECK-NEXT: notifyOperationInserted: unregistered.bar +// CHECK-NEXT: notifyOperationInserted: unregistered.empty_dict +// CHECK-NEXT: notifyOperationInserted: unregistered.complex +// CHECK-NEXT: notifyOperationInserted: func.return + +// CHECK-LABEL: func @clone_unregistered_with_attrs() { +// CHECK-NEXT: "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = [[PI:.+]] : f32}> : () -> () +// CHECK-NEXT: "unregistered.bar"() : () -> () +// CHECK-NEXT: "unregistered.empty_dict"() <{}> : () -> () +// CHECK-NEXT: "unregistered.complex"() <{array = [1, 2, 3], dict = {key1 = 42 : i32, key2 = "value"}, nested = {inner = {deep = 100 : i64}}}> : () -> () +// CHECK-NEXT: "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = [[PI]] : f32}> : () -> () +// CHECK-NEXT: "unregistered.bar"() : () -> () +// CHECK-NEXT: "unregistered.empty_dict"() <{}> : () -> () +// CHECK-NEXT: "unregistered.complex"() <{array = [1, 2, 3], dict = {key1 = 42 : i32, key2 = "value"}, nested = {inner = {deep = 100 : i64}}}> : () -> () diff --git a/mlir/test/IR/test-symbol-rauw.mlir b/mlir/test/IR/test-symbol-rauw.mlir index ba17cf9d10426..1acd834fcde8e 100644 --- a/mlir/test/IR/test-symbol-rauw.mlir +++ b/mlir/test/IR/test-symbol-rauw.mlir @@ -51,11 +51,12 @@ module { } } - // CHECK: func @symbol_bar + // FIXME:#73140 + // DISABLED-CHECK: func @symbol_bar func.func @symbol_bar() { - // CHECK: foo.op - // CHECK-SAME: use_1 = @module_a::@replaced_foo - // CHECK-SAME: use_2 = @replaced_module_b::@replaced_module_c::@replaced_foo + // DISABLED-CHECK: foo.op + // DISABLED-CHECK-SAME: use_1 = @module_a::@replaced_foo + // DISABLED-CHECK-SAME: use_2 = @replaced_module_b::@replaced_module_c::@replaced_foo "foo.op"() { use_1 = @module_a::@foo, use_2 = @module_b::@module_c::@foo @@ -97,15 +98,16 @@ module { // ----- +// FIXME:#73140 module { - // CHECK: module @replaced_foo + // DISABLED-CHECK: module @replaced_foo module @foo attributes {sym.new_name = "replaced_foo" } { - // CHECK: func.func private @foo + // DISABLED-CHECK: func.func private @foo func.func private @foo() } - // CHECK: foo.op - // CHECK-SAME: use = @replaced_foo::@foo + // DISABLED-CHECK: foo.op + // DISABLED-CHECK-SAME: use = @replaced_foo::@foo "foo.op"() { use = @foo::@foo } : () -> () diff --git a/mlir/test/IR/test-walk-pattern-rewrite-driver.mlir b/mlir/test/IR/test-walk-pattern-rewrite-driver.mlir index 02f7e60671c9b..c3063416b0360 100644 --- a/mlir/test/IR/test-walk-pattern-rewrite-driver.mlir +++ b/mlir/test/IR/test-walk-pattern-rewrite-driver.mlir @@ -40,12 +40,12 @@ func.func @move_before(%cond : i1) { } // Check that the driver handles rewriter.moveAfter. In this case, we expect -// the moved op to be visited only once since walk uses `make_early_inc_range`. +// the moved op to be visited twice. // CHECK-LABEL: func.func @move_after( // CHECK: scf.if // CHECK: } // CHECK: "test.move_after_parent_op" -// CHECK: "test.any_attr_of_i32_str"() <{attr = 1 : i32}> : () -> () +// CHECK: "test.any_attr_of_i32_str"() <{attr = 2 : i32}> : () -> () // CHECK: return func.func @move_after(%cond : i1) { scf.if %cond { @@ -119,3 +119,23 @@ func.func @erase_nested_block() -> i32 { }): () -> (i32) return %a : i32 } + + +// CHECK-LABEL: func.func @unreachable_replace_with_new_op +// CHECK: "test.new_op" +// CHECK: "test.replace_with_new_op" +// CHECK-SAME: unreachable +// CHECK: "test.new_op" +func.func @unreachable_replace_with_new_op() { + "test.br"()[^bb1] : () -> () +^bb1: + %a = "test.replace_with_new_op"() : () -> (i32) + "test.br"()[^end] : () -> () // Test jumping over the unreachable block is visited as well. +^unreachable: + %b = "test.replace_with_new_op"() {test.unreachable} : () -> (i32) + return +^end: + %c = "test.replace_with_new_op"() : () -> (i32) + return +} + diff --git a/mlir/test/IR/traits.mlir b/mlir/test/IR/traits.mlir index 49cfd7e496746..85deff0386900 100644 --- a/mlir/test/IR/traits.mlir +++ b/mlir/test/IR/traits.mlir @@ -591,13 +591,15 @@ func.func @failedHasDominanceScopeOutsideDominanceFreeScope() -> () { // Ensure that SSACFG regions of operations in GRAPH regions are // checked for dominance -func.func @illegalInsideDominanceFreeScope(%cond: i1) -> () { +func.func @illegalInsideDominanceFreeScope() -> () { test.graph_region { - scf.if %cond { + func.func @test() -> i1 { + ^bb1: // expected-error @+1 {{operand #0 does not dominate this use}} %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) // expected-note @+1 {{operand defined here}} - %1 = "baz"(%2#0) : (i1) -> (i64) + %1 = "baz"(%2#0) : (i1) -> (i64) + return %2#1 : i1 } "terminator"() : () -> () } @@ -608,21 +610,20 @@ func.func @illegalInsideDominanceFreeScope(%cond: i1) -> () { // Ensure that SSACFG regions of operations in GRAPH regions are // checked for dominance -func.func @illegalCFGInsideDominanceFreeScope(%cond: i1) -> () { +func.func @illegalCDFGInsideDominanceFreeScope() -> () { test.graph_region { - scf.if %cond { - "test.ssacfg_region"() ({ - ^bb1: - // expected-error @+1 {{operand #0 does not dominate this use}} - %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) - cf.br ^bb4 - ^bb2: - cf.br ^bb2 - ^bb4: - %1 = "foo"() : ()->i64 // expected-note {{operand defined here}} - }) : () -> () + func.func @test() -> i1 { + ^bb1: + // expected-error @+1 {{operand #0 does not dominate this use}} + %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) + cf.br ^bb4 + ^bb2: + cf.br ^bb2 + ^bb4: + %1 = "foo"() : ()->i64 // expected-note {{operand defined here}} + return %2#1 : i1 } - "terminator"() : () -> () + "terminator"() : () -> () } return } diff --git a/mlir/test/Pass/pipeline-options-parsing.mlir b/mlir/test/Pass/pipeline-options-parsing.mlir index 9385d353faf95..03ac38ea16112 100644 --- a/mlir/test/Pass/pipeline-options-parsing.mlir +++ b/mlir/test/Pass/pipeline-options-parsing.mlir @@ -13,6 +13,7 @@ // RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(builtin.module(func.func(test-options-pass{list=3}), func.func(test-options-pass{enum=one list=1,2,3,4 string=foo"bar"baz})))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_6 %s // RUN: mlir-opt %s -verify-each=false '-test-options-super-pass-pipeline=super-list={{enum=zero list=1 string=foo},{enum=one list=2 string="bar"},{enum=two list=3 string={baz}}}' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_7 %s // RUN: mlir-opt %s -verify-each=false -pass-pipeline='builtin.module(func.func(test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one list={2} string=bar },{enum=two list={3} string=baz }}}))' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_7 %s +// RUN: mlir-opt %s -verify-each=false -test-options-super-set-ab-pipeline='foo=true bar=false' -dump-pass-pipeline 2>&1 | FileCheck --check-prefix=CHECK_11 %s // This test checks that lists-of-nested-options like 'option1={...},{....}' can be parsed @@ -106,3 +107,12 @@ // CHECK_10-NEXT: test-options-pass{enum=zero string= string-list={,}} // CHECK_10-NEXT: ) // CHECK_10-NEXT: ) + +// CHECK_11: builtin.module( +// CHECK_11-NEXT: func.func( +// CHECK_11-NEXT: test-options-pass-a +// CHECK_11-NEXT: ) +// CHECK_11-NEXT: func.func( +// CHECK_11-NEXT: test-options-pass-b +// CHECK_11-NEXT: ) +// CHECK_11-NEXT: ) diff --git a/mlir/test/Transforms/canonicalize-dce.mlir b/mlir/test/Transforms/canonicalize-dce.mlir index 84631947970de..e8608a3aa3e69 100644 --- a/mlir/test/Transforms/canonicalize-dce.mlir +++ b/mlir/test/Transforms/canonicalize-dce.mlir @@ -77,15 +77,15 @@ func.func @f(%arg0: f32, %pred: i1) { // Test case: Recursively DCE into enclosed regions. -// CHECK: func.func @f(%arg0: f32) -// CHECK-NOT: arith.addf +// CHECK: func @f(%arg0: f32) +// CHECK-NEXT: func @g(%arg1: f32) +// CHECK-NEXT: return func.func @f(%arg0: f32) { - "test.region"() ( - { - %0 = "arith.addf"(%arg0, %arg0) : (f32, f32) -> f32 - } - ) : () -> () + func.func @g(%arg1: f32) { + %0 = "arith.addf"(%arg1, %arg1) : (f32, f32) -> f32 + return + } return } diff --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir index 8e02c06a0a293..eff2cd609b51c 100644 --- a/mlir/test/Transforms/canonicalize.mlir +++ b/mlir/test/Transforms/canonicalize.mlir @@ -429,15 +429,16 @@ func.func @write_only_alloca_fold(%v: f32) { // CHECK-LABEL: func @dead_block_elim func.func @dead_block_elim() { // CHECK-NOT: ^bb - builtin.module { - func.func @nested() { - return + func.func @nested() { + return - ^bb1: - return - } + ^bb1: + return } return + +^bb1: + return } // CHECK-LABEL: func @dyn_shape_fold(%arg0: index, %arg1: index) diff --git a/mlir/test/Transforms/constant-fold.mlir b/mlir/test/Transforms/constant-fold.mlir index 0b393bf0556b9..eb530dace319f 100644 --- a/mlir/test/Transforms/constant-fold.mlir +++ b/mlir/test/Transforms/constant-fold.mlir @@ -794,15 +794,12 @@ func.func @cmpf_inf() -> (i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1 // CHECK-LABEL: func @nested_isolated_region func.func @nested_isolated_region() { - // CHECK-NEXT: builtin.module { // CHECK-NEXT: func @isolated_op // CHECK-NEXT: arith.constant 2 - builtin.module { - func.func @isolated_op() { - %0 = arith.constant 1 : i32 - %2 = arith.addi %0, %0 : i32 - "foo.yield"(%2) : (i32) -> () - } + func.func @isolated_op() { + %0 = arith.constant 1 : i32 + %2 = arith.addi %0, %0 : i32 + "foo.yield"(%2) : (i32) -> () } // CHECK: "foo.unknown_region" diff --git a/mlir/test/Transforms/cse.mlir b/mlir/test/Transforms/cse.mlir index b447094874d01..84fb9c4591de5 100644 --- a/mlir/test/Transforms/cse.mlir +++ b/mlir/test/Transforms/cse.mlir @@ -252,14 +252,11 @@ func.func @nested_isolated() -> i32 { // CHECK-NEXT: arith.constant 1 %0 = arith.constant 1 : i32 - // CHECK-NEXT: builtin.module // CHECK-NEXT: @nested_func - builtin.module { - func.func @nested_func() { - // CHECK-NEXT: arith.constant 1 - %foo = arith.constant 1 : i32 - "foo.yield"(%foo) : (i32) -> () - } + func.func @nested_func() { + // CHECK-NEXT: arith.constant 1 + %foo = arith.constant 1 : i32 + "foo.yield"(%foo) : (i32) -> () } // CHECK: "foo.region" diff --git a/mlir/test/Transforms/remove-dead-values.mlir b/mlir/test/Transforms/remove-dead-values.mlir index 3af95db3c0e24..0f8d757086e87 100644 --- a/mlir/test/Transforms/remove-dead-values.mlir +++ b/mlir/test/Transforms/remove-dead-values.mlir @@ -548,3 +548,47 @@ func.func @test_atomic_yield(%I: memref<10xf32>, %idx : index) { func.return } +// ----- + +// CHECK-LABEL: module @return_void_with_unused_argument +module @return_void_with_unused_argument { + // CHECK-LABEL: func.func private @fn_return_void_with_unused_argument + // CHECK-SAME: (%[[ARG0_FN:.*]]: i32) + func.func private @fn_return_void_with_unused_argument(%arg0: i32, %arg1: memref<4xi32>) -> () { + %sum = arith.addi %arg0, %arg0 : i32 + %c0 = arith.constant 0 : index + %buf = memref.alloc() : memref<1xi32> + memref.store %sum, %buf[%c0] : memref<1xi32> + return + } + // CHECK-LABEL: func.func @main + // CHECK-SAME: (%[[ARG0_MAIN:.*]]: i32) + // CHECK: call @fn_return_void_with_unused_argument(%[[ARG0_MAIN]]) : (i32) -> () + func.func @main(%arg0: i32) -> memref<4xi32> { + %unused = memref.alloc() : memref<4xi32> + call @fn_return_void_with_unused_argument(%arg0, %unused) : (i32, memref<4xi32>) -> () + return %unused : memref<4xi32> + } +} + +// ----- + +// CHECK-LABEL: module @dynamically_unreachable +module @dynamically_unreachable { + func.func @dynamically_unreachable() { + // This value is used by an operation in a dynamically unreachable block. + %zero = arith.constant 0 : i64 + + // Dataflow analysis knows from the constant condition that + // ^bb1 is unreachable + %false = arith.constant false + cf.cond_br %false, ^bb1, ^bb4 + ^bb1: + // This unreachable operation should be removed. + // CHECK-NOT: arith.cmpi + %3 = arith.cmpi eq, %zero, %zero : i64 + cf.br ^bb1 + ^bb4: + return + } +} diff --git a/mlir/test/Transforms/test-canonicalize.mlir b/mlir/test/Transforms/test-canonicalize.mlir index 0fc822b0a23ae..8cad6b98441df 100644 --- a/mlir/test/Transforms/test-canonicalize.mlir +++ b/mlir/test/Transforms/test-canonicalize.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize))' | FileCheck %s +// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize))' | FileCheck %s --check-prefixes=CHECK,RS // RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{region-simplify=disabled}))' | FileCheck %s --check-prefixes=CHECK,NO-RS // CHECK-LABEL: func @remove_op_with_inner_ops_pattern @@ -80,12 +80,10 @@ func.func @test_dialect_canonicalizer() -> (i32) { // Check that the option to control region simplification actually works // CHECK-LABEL: test_region_simplify -func.func @test_region_simplify() { - // CHECK-NEXT: return - // NO-RS-NEXT: ^bb1 - // NO-RS-NEXT: return - // CHECK-NEXT: } - return -^bb1: - return +func.func @test_region_simplify(%input1 : i32, %cond : i1) -> i32 { + // RS-NEXT: "test.br"(%arg0)[^bb1] : (i32) -> () + // NO-RS-NEXT: "test.br"(%arg0, %arg0)[^bb1] : (i32, i32) -> () + "test.br"(%input1, %input1)[^bb1] : (i32, i32) -> () +^bb1(%used_arg : i32, %unused_arg : i32): + return %used_arg : i32 } diff --git a/mlir/test/Transforms/test-legalizer-full.mlir b/mlir/test/Transforms/test-legalizer-full.mlir index 5f1148cac6501..74f312e8144a0 100644 --- a/mlir/test/Transforms/test-legalizer-full.mlir +++ b/mlir/test/Transforms/test-legalizer-full.mlir @@ -37,11 +37,9 @@ func.func @recursively_legal_invalid_op() { } /// Operation that is dynamically legal, i.e. the function has a pattern /// applied to legalize the argument type before it becomes recursively legal. - builtin.module { - func.func @dynamic_func(%arg: i64) attributes {test.recursively_legal} { - %ignored = "test.illegal_op_f"() : () -> (i32) - "test.return"() : () -> () - } + func.func @dynamic_func(%arg: i64) attributes {test.recursively_legal} { + %ignored = "test.illegal_op_f"() : () -> (i32) + "test.return"() : () -> () } "test.return"() : () -> () diff --git a/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp index 43005e22584c2..8e2f03b644e49 100644 --- a/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp +++ b/mlir/test/lib/Analysis/DataFlow/TestLivenessAnalysis.cpp @@ -33,7 +33,6 @@ struct TestLivenessAnalysisPass void runOnOperation() override { auto &livenessAnalysis = getAnalysis(); - Operation *op = getOperation(); raw_ostream &os = llvm::outs(); diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td index 382da592d0079..f98250c40f384 100644 --- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td +++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td @@ -347,6 +347,7 @@ def TestCopyCount : Test_Attr<"TestCopyCount"> { let mnemonic = "copy_count"; let parameters = (ins TestParamCopyCount:$copy_count); let assemblyFormat = "`<` $copy_count `>`"; + let genVerifyDecl = 1; } def TestConditionalAliasAttr : Test_Attr<"TestConditionalAlias"> { @@ -438,4 +439,10 @@ def TestCustomStorageCtorAttr : Test_Attr<"TestCustomStorageCtorAttr"> { let hasStorageCustomConstructor = 1; } +def TestAttrNewlineAndIndent : Test_Attr<"TestAttrNewlineAndIndent"> { + let mnemonic = "newline_and_indent"; + let parameters = (ins "::mlir::Type":$indentType); + let hasCustomAssemblyFormat = 1; +} + #endif // TEST_ATTRDEFS diff --git a/mlir/test/lib/Dialect/Test/TestAttributes.cpp b/mlir/test/lib/Dialect/Test/TestAttributes.cpp index b31e90fc9ca91..8e28447a6ec61 100644 --- a/mlir/test/lib/Dialect/Test/TestAttributes.cpp +++ b/mlir/test/lib/Dialect/Test/TestAttributes.cpp @@ -213,6 +213,16 @@ static void printTrueFalse(AsmPrinter &p, std::optional result) { p << (*result ? "true" : "false"); } +//===----------------------------------------------------------------------===// +// TestCopyCountAttr Implementation +//===----------------------------------------------------------------------===// + +LogicalResult TestCopyCountAttr::verify( + llvm::function_ref<::mlir::InFlightDiagnostic()> /*emitError*/, + CopyCount /*copy_count*/) { + return success(); +} + //===----------------------------------------------------------------------===// // CopyCountAttr Implementation //===----------------------------------------------------------------------===// @@ -420,6 +430,30 @@ bool TestConstMemorySpaceAttr::isValidPtrIntCast( return false; } +//===----------------------------------------------------------------------===// +// TestAttrNewlineAndIndent +//===----------------------------------------------------------------------===// + +Attribute TestAttrNewlineAndIndentAttr::parse(::mlir::AsmParser &parser, + ::mlir::Type type) { + Type indentType; + if (parser.parseLess() || parser.parseType(indentType) || + parser.parseGreater()) { + return Attribute(); + } + return get(parser.getContext(), indentType); +} + +void TestAttrNewlineAndIndentAttr::print(::mlir::AsmPrinter &printer) const { + printer << "<"; + printer.increaseIndent(); + printer.printNewline(); + printer << getIndentType(); + printer.decreaseIndent(); + printer.printNewline(); + printer << ">"; +} + //===----------------------------------------------------------------------===// // Tablegen Generated Definitions //===----------------------------------------------------------------------===// diff --git a/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp b/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp index 6d4e5e3cb4401..e8ec888502e53 100644 --- a/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp +++ b/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp @@ -153,6 +153,12 @@ static ParseResult parseCustomDirectiveOptionalOperandRef( bool expectedOptionalOperand = operandCount == 0; return success(expectedOptionalOperand != optOperand.has_value()); } +static ParseResult parseOptionalType(OpAsmParser &parser, Type &type) { + if (parser.parseOptionalColon()) + return success(); + + return parser.parseType(type); +} //===----------------------------------------------------------------------===// // Printing @@ -234,6 +240,21 @@ static void printCustomDirectiveOptionalOperandRef(OpAsmPrinter &printer, Value optOperand) { printer << (optOperand ? "1" : "0"); } +static bool isDefinedAbove(Value val, Operation *op) { + if (mlir::isa(val)) + return true; + + return val.getDefiningOp()->getBlock() == op->getBlock() && + val.getDefiningOp()->isBeforeInBlock(op); +} +static void printOptionalType(OpAsmPrinter &printer, + FormatOperandOptionalTypeOp op, Type type) { + if (isDefinedAbove(op.getOperand(), op)) + return; + + printer << ":"; + printer.printType(type); +} //===----------------------------------------------------------------------===// // Test parser. //===----------------------------------------------------------------------===// diff --git a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td index 9a96fe8b11c14..3af6f187c4f3b 100644 --- a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td +++ b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td @@ -309,6 +309,9 @@ def FormatOperandDOp : FormatOperandBase<"d", [{ def FormatOperandEOp : FormatOperandBase<"e", [{ $buildable `,` $operand `:` type($buildable) `,` type($operand) attr-dict }]>; +def FormatOperandOptionalTypeOp : FormatOperandBase<"optional_type", [{ + $buildable `,` $operand custom(type($operand)) attr-dict +}]>; def FormatSuccessorAOp : TEST_Op<"format_successor_a_op", [Terminator]> { let successors = (successor VariadicSuccessor:$targets); diff --git a/mlir/test/lib/Dialect/Test/TestTypeDefs.td b/mlir/test/lib/Dialect/Test/TestTypeDefs.td index ea20597231d58..070ad0e6e56c4 100644 --- a/mlir/test/lib/Dialect/Test/TestTypeDefs.td +++ b/mlir/test/lib/Dialect/Test/TestTypeDefs.td @@ -470,4 +470,9 @@ def TestMemrefType : Test_Type<"TestMemref", }]; } +def TestTypeNewlineAndIndent : Test_Type<"TestTypeNewlineAndIndent"> { + let mnemonic = "newline_and_indent"; + let hasCustomAssemblyFormat = 1; +} + #endif // TEST_TYPEDEFS diff --git a/mlir/test/lib/Dialect/Test/TestTypes.cpp b/mlir/test/lib/Dialect/Test/TestTypes.cpp index bea043f56fe21..7d33b89e76760 100644 --- a/mlir/test/lib/Dialect/Test/TestTypes.cpp +++ b/mlir/test/lib/Dialect/Test/TestTypes.cpp @@ -565,11 +565,39 @@ TestTensorType::getBufferType( ::mlir::LogicalResult TestTensorType::verifyCompatibleBufferType( ::mlir::bufferization::BufferLikeType bufferType, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) { - auto testMemref = dyn_cast(bufferType); - if (!testMemref) - return emitError() << "expected TestMemrefType"; + if (auto testMemref = dyn_cast(bufferType)) { + const bool valid = getShape() == testMemref.getShape() && + getElementType() == testMemref.getElementType(); + return mlir::success(valid); + } + + if (auto builtinMemref = dyn_cast(bufferType)) { + const bool valid = getShape() == builtinMemref.getShape() && + getElementType() == builtinMemref.getElementType(); + return mlir::success(valid); + } - const bool valid = getShape() == testMemref.getShape() && - getElementType() == testMemref.getElementType(); - return mlir::success(valid); + return emitError() << "expected MemRefType or TestMemrefType"; +} + +//===----------------------------------------------------------------------===// +// TestTypeNewlineAndIndent +//===----------------------------------------------------------------------===// + +Type TestTypeNewlineAndIndentType::parse(::mlir::AsmParser &parser) { + if (parser.parseLess() || parser.parseKeyword("indented_content") || + parser.parseGreater()) { + return Type(); + } + return get(parser.getContext()); +} + +void TestTypeNewlineAndIndentType::print(::mlir::AsmPrinter &printer) const { + printer << "<"; + printer.increaseIndent(); + printer.printNewline(); + printer << "indented_content"; + printer.decreaseIndent(); + printer.printNewline(); + printer << ">"; } diff --git a/mlir/test/lib/Pass/TestPassManager.cpp b/mlir/test/lib/Pass/TestPassManager.cpp index 7afe2109f04db..2b5f75ef53f16 100644 --- a/mlir/test/lib/Pass/TestPassManager.cpp +++ b/mlir/test/lib/Pass/TestPassManager.cpp @@ -133,6 +133,51 @@ struct TestOptionsSuperPass llvm::cl::desc("Example list of PassPipelineOptions option")}; }; +struct TestOptionsPassA + : public PassWrapper> { + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPassA) + + struct Options : public PassPipelineOptions { + Option foo{*this, "foo", llvm::cl::desc("Example boolean option")}; + }; + + TestOptionsPassA() = default; + TestOptionsPassA(const TestOptionsPassA &) : PassWrapper() {} + TestOptionsPassA(const Options &options) { this->options.foo = options.foo; } + + void runOnOperation() final {} + StringRef getArgument() const final { return "test-options-pass-a"; } + StringRef getDescription() const final { + return "Test superset options parsing capabilities - subset A"; + } + + Options options; +}; + +struct TestOptionsPassB + : public PassWrapper> { + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestOptionsPassB) + + struct Options : public PassPipelineOptions { + Option bar{*this, "bar", llvm::cl::desc("Example boolean option")}; + }; + + TestOptionsPassB() = default; + TestOptionsPassB(const TestOptionsPassB &) : PassWrapper() {} + TestOptionsPassB(const Options &options) { this->options.bar = options.bar; } + + void runOnOperation() final {} + StringRef getArgument() const final { return "test-options-pass-b"; } + StringRef getDescription() const final { + return "Test superset options parsing capabilities - subset B"; + } + + Options options; +}; + +struct TestPipelineOptionsSuperSetAB : TestOptionsPassA::Options, + TestOptionsPassB::Options {}; + /// A test pass that always aborts to enable testing the crash recovery /// mechanism of the pass manager. struct TestCrashRecoveryPass @@ -270,6 +315,9 @@ void registerPassManagerTestPass() { PassRegistration(); PassRegistration(); + PassRegistration(); + PassRegistration(); + PassRegistration(); PassRegistration(); @@ -306,5 +354,16 @@ void registerPassManagerTestPass() { [](OpPassManager &pm, const TestOptionsSuperPass::Options &options) { pm.addPass(std::make_unique(options)); }); + + PassPipelineRegistration + registerPipelineOptionsSuperSetABPipeline( + "test-options-super-set-ab-pipeline", + "Parses options of PassPipelineOptions using pass pipeline " + "registration", + [](OpPassManager &pm, const TestPipelineOptionsSuperSetAB &options) { + // Pass superset AB options to subset options A and B + pm.addPass(std::make_unique(options)); + pm.addPass(std::make_unique(options)); + }); } } // namespace mlir diff --git a/mlir/test/mlir-tblgen/attrdefs.td b/mlir/test/mlir-tblgen/attrdefs.td index d47411d6e860a..a809611fd0aec 100644 --- a/mlir/test/mlir-tblgen/attrdefs.td +++ b/mlir/test/mlir-tblgen/attrdefs.td @@ -115,6 +115,11 @@ def B_CompoundAttrA : TestAttr<"CompoundA"> { // DEF: return new (allocator.allocate()) // DEF-SAME: CompoundAAttrStorage(std::move(widthOfSomething), std::move(exampleTdType), std::move(apFloat), std::move(dims), std::move(inner)); +// DEF: CompoundAAttr CompoundAAttr::getChecked( +// DEF-SAME: int widthOfSomething, ::test::SimpleTypeA exampleTdType, ::llvm::APFloat apFloat, ::llvm::ArrayRef dims, ::mlir::Type inner +// DEF-SAME: ) +// DEF-NEXT: return Base::getChecked(emitError, context, std::move(widthOfSomething), std::move(exampleTdType), std::move(apFloat), std::move(dims), std::move(inner)); + // DEF: ::mlir::Type CompoundAAttr::getInner() const { // DEF-NEXT: return getImpl()->inner; } diff --git a/mlir/test/mlir-tblgen/enums-python-bindings.td b/mlir/test/mlir-tblgen/enums-python-bindings.td index 1c5567f54a5f4..cd23b6a2effb9 100644 --- a/mlir/test/mlir-tblgen/enums-python-bindings.td +++ b/mlir/test/mlir-tblgen/enums-python-bindings.td @@ -62,12 +62,15 @@ def MyEnum64 : I64EnumAttr<"MyEnum64", "An example 64-bit enum", [One64, Two64]> // CHECK: def _myenum64(x, context): // CHECK: return _ods_ir.IntegerAttr.get(_ods_ir.IntegerType.get_signless(64, context=context), int(x)) +def User : I32BitEnumAttrCaseBit<"User", 0, "user">; +def Group : I32BitEnumAttrCaseBit<"Group", 1, "group">; +def Other : I32BitEnumAttrCaseBit<"Other", 2, "other">; + def TestBitEnum - : I32BitEnumAttr<"TestBitEnum", "", [ - I32BitEnumAttrCaseBit<"User", 0, "user">, - I32BitEnumAttrCaseBit<"Group", 1, "group">, - I32BitEnumAttrCaseBit<"Other", 2, "other">, - ]> { + : I32BitEnumAttr< + "TestBitEnum", "", + [User, Group, Other, + I32BitEnumAttrCaseGroup<"Any", [User, Group, Other], "any">]> { let genSpecializedAttr = 0; let separator = " | "; } @@ -79,9 +82,10 @@ def TestBitEnum_Attr : EnumAttr; // CHECK: User = 1 // CHECK: Group = 2 // CHECK: Other = 4 +// CHECK: Any = 7 // CHECK: def __iter__(self): -// CHECK: return iter([case for case in type(self) if (self & case) is case]) +// CHECK: return iter([case for case in type(self) if (self & case) is case and self is not case]) // CHECK: def __len__(self): // CHECK: return bin(self).count("1") @@ -94,6 +98,8 @@ def TestBitEnum_Attr : EnumAttr; // CHECK: return "group" // CHECK: if self is TestBitEnum.Other: // CHECK: return "other" +// CHECK: if self is TestBitEnum.Any: +// CHECK: return "any" // CHECK: raise ValueError("Unknown TestBitEnum enum entry.") // CHECK: @register_attribute_builder("TestBitEnum") diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td index f213f50ae2f39..351f11f8c9082 100644 --- a/mlir/test/mlir-tblgen/op-decl-and-defs.td +++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td @@ -236,14 +236,14 @@ def NS_FOp : NS_Op<"op_with_all_types_constraint", // DEFS: FOp FOp::create(::mlir::OpBuilder &builder, ::mlir::Location location, ::mlir::Value a) { // DEFS: ::mlir::OperationState __state__(location, getOperationName()); -// DEFS: build(builder, __state__, a); +// DEFS: build(builder, __state__, std::forward(a)); // DEFS: auto __res__ = ::llvm::dyn_cast(builder.create(__state__)); // DEFS: assert(__res__ && "builder didn't return the right type"); // DEFS: return __res__; // DEFS: } // DEFS: FOp FOp::create(::mlir::ImplicitLocOpBuilder &builder, ::mlir::Value a) { -// DEFS: return create(builder, builder.getLoc(), a); +// DEFS: return create(builder, builder.getLoc(), std::forward(a)); // DEFS: } def NS_GOp : NS_Op<"op_with_fixed_return_type", []> { diff --git a/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir b/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir index 89ad3594eebd8..dca46a30e37f1 100644 --- a/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir +++ b/mlir/test/mlir-tblgen/testdialect-attrdefs.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -split-input-file -verify-diagnostics | FileCheck %s +// RUN: mlir-opt %s -split-input-file -verify-diagnostics | FileCheck %s --strict-whitespace // CHECK-LABEL: func private @compoundA() // CHECK-SAME: #test.cmpnd_a<1, !test.smpla, [5, 6]> @@ -44,3 +44,19 @@ func.func private @hexdecimalInteger() attributes { // expected-error @below {{expected an integer}} sdg = #test.decimal_shape<1x0xb> } + +// ----- + +// CHECK-LABEL: @newlineAndIndent +// CHECK-SAME: indent = #test.newline_and_indent< +// CHECK-NEXT: {{^ }}!test.newline_and_indent< +// CHECK-NEXT: {{^ }}indented_content +// CHECK-NEXT: {{^ }}> +// CHECK-NEXT: {{^ }}> +func.func private @newlineAndIndent() attributes { + indent = #test.newline_and_indent< + !test.newline_and_indent< + indented_content + > + > +} diff --git a/mlir/test/mlir-tblgen/testdialect-typedefs.mlir b/mlir/test/mlir-tblgen/testdialect-typedefs.mlir index 18175edc81cf0..c00d368fdab8b 100644 --- a/mlir/test/mlir-tblgen/testdialect-typedefs.mlir +++ b/mlir/test/mlir-tblgen/testdialect-typedefs.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s | mlir-opt -verify-diagnostics | FileCheck %s +// RUN: mlir-opt %s | mlir-opt -verify-diagnostics | FileCheck %s --strict-whitespace ////////////// // Tests the types in the 'Test' dialect, not the ones in 'typedefs.mlir' @@ -42,3 +42,13 @@ func.func @testInt(%A : !test.int, %B : !test.int, %C : !test func.func @structTest (%A : !test.struct< {field1, !test.smpla}, {field2, !test.int} > ) { return } + +// CHECK-LABEL: @newlineAndIndent +// CHECK-SAME: !test.newline_and_indent< +// CHECK-NEXT: {{^ }}indented_content +// CHECK-NEXT: {{^ }}> +func.func @newlineAndIndent(%A : !test.newline_and_indent< + indented_content +>) { + return +} diff --git a/mlir/test/python/ir/value.py b/mlir/test/python/ir/value.py index 4a241afb8e89d..5f30da5a61f63 100644 --- a/mlir/test/python/ir/value.py +++ b/mlir/test/python/ir/value.py @@ -237,15 +237,28 @@ def testValuePrintAsOperand(): print(value2) topFn = func.FuncOp("test", ([i32, i32], [])) - entry_block = Block.create_at_start(topFn.operation.regions[0], [i32, i32]) + entry_block1 = Block.create_at_start(topFn.operation.regions[0], [i32, i32]) - with InsertionPoint(entry_block): + with InsertionPoint(entry_block1): value3 = Operation.create("custom.op3", results=[i32]).results[0] # CHECK: Value(%[[VAL3:.*]] = "custom.op3"() : () -> i32) print(value3) value4 = Operation.create("custom.op4", results=[i32]).results[0] # CHECK: Value(%[[VAL4:.*]] = "custom.op4"() : () -> i32) print(value4) + + f = func.FuncOp("test", ([i32, i32], [])) + entry_block2 = Block.create_at_start(f.operation.regions[0], [i32, i32]) + with InsertionPoint(entry_block2): + value5 = Operation.create("custom.op5", results=[i32]).results[0] + # CHECK: Value(%[[VAL5:.*]] = "custom.op5"() : () -> i32) + print(value5) + value6 = Operation.create("custom.op6", results=[i32]).results[0] + # CHECK: Value(%[[VAL6:.*]] = "custom.op6"() : () -> i32) + print(value6) + + func.ReturnOp([]) + func.ReturnOp([]) # CHECK: %[[VAL1]] @@ -272,10 +285,20 @@ def testValuePrintAsOperand(): # CHECK: %1 print(value4.get_name(use_local_scope=True)) + # CHECK: %[[VAL5]] + print(value5.get_name()) + # CHECK: %[[VAL6]] + print(value6.get_name()) + # CHECK: %[[ARG0:.*]] - print(entry_block.arguments[0].get_name()) + print(entry_block1.arguments[0].get_name()) # CHECK: %[[ARG1:.*]] - print(entry_block.arguments[1].get_name()) + print(entry_block1.arguments[1].get_name()) + + # CHECK: %[[ARG2:.*]] + print(entry_block2.arguments[0].get_name()) + # CHECK: %[[ARG3:.*]] + print(entry_block2.arguments[1].get_name()) # CHECK: module { # CHECK: %[[VAL1]] = "custom.op1"() : () -> i32 @@ -283,6 +306,11 @@ def testValuePrintAsOperand(): # CHECK: func.func @test(%[[ARG0]]: i32, %[[ARG1]]: i32) { # CHECK: %[[VAL3]] = "custom.op3"() : () -> i32 # CHECK: %[[VAL4]] = "custom.op4"() : () -> i32 + # CHECK: func @test(%[[ARG2]]: i32, %[[ARG3]]: i32) { + # CHECK: %[[VAL5]] = "custom.op5"() : () -> i32 + # CHECK: %[[VAL6]] = "custom.op6"() : () -> i32 + # CHECK: return + # CHECK: } # CHECK: return # CHECK: } # CHECK: } diff --git a/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp b/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp index 9ec9b72150207..9271bc4bd7dcf 100644 --- a/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp +++ b/mlir/tools/mlir-src-sharder/mlir-src-sharder.cpp @@ -72,6 +72,12 @@ int main(int argc, char **argv) { "Name of the macro to be defined -- ignored by mlir-src-sharder"), llvm::cl::value_desc("macro name"), llvm::cl::Prefix); + // CMake/TableGen pass this flag, re-registering after ResetCommandLineParser + // avoids "unknown argument" errors. + llvm::cl::opt noWarnOnUnusedTemplateArg( + "no-warn-on-unused-template-args", + llvm::cl::desc("Disable unused template argument warnings.")); + llvm::InitLLVM y(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv); diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp index dbae2143b920a..3140f12c0b7e8 100644 --- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp @@ -495,7 +495,7 @@ void DefGen::emitCheckedBuilder() { MethodBody &body = m->body().indent(); auto scope = body.scope("return Base::getChecked(emitError, context", ");"); for (const auto ¶m : params) - body << ", " << param.getName(); + body << ", std::move(" << param.getName() << ")"; } static SmallVector diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp index 10a162f81ba13..ace73db03f569 100644 --- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp @@ -958,9 +958,7 @@ void DefFormat::genOptionalGroupPrinter(OptionalElement *el, FmtContext &ctx, void DefFormat::genWhitespacePrinter(WhitespaceElement *el, FmtContext &ctx, MethodBody &os) { if (el->getValue() == "\\n") { - // FIXME: The newline should be `printer.printNewLine()`, i.e., handled by - // the printer. - os << tgfmt("$_printer << '\\n';\n", &ctx); + os << tgfmt("$_printer.printNewline();\n", &ctx); } else if (!el->getValue().empty()) { os << tgfmt("$_printer << \"$0\";\n", &ctx, el->getValue()); } else { diff --git a/mlir/tools/mlir-tblgen/EnumPythonBindingGen.cpp b/mlir/tools/mlir-tblgen/EnumPythonBindingGen.cpp index 8e2d6114e48eb..acc9b61d7121c 100644 --- a/mlir/tools/mlir-tblgen/EnumPythonBindingGen.cpp +++ b/mlir/tools/mlir-tblgen/EnumPythonBindingGen.cpp @@ -64,7 +64,7 @@ static void emitEnumClass(EnumInfo enumInfo, raw_ostream &os) { if (enumInfo.isBitEnum()) { os << formatv(" def __iter__(self):\n" " return iter([case for case in type(self) if " - "(self & case) is case])\n"); + "(self & case) is case and self is not case])\n"); os << formatv(" def __len__(self):\n" " return bin(self).count(\"1\")\n"); os << "\n"; diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index f35cfa6826388..b5dc6202724b6 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -2616,7 +2616,14 @@ void OpEmitter::genInlineCreateBody( std::string nonBuilderStateArgs = ""; if (!nonBuilderStateArgsList.empty()) { llvm::raw_string_ostream nonBuilderStateArgsOS(nonBuilderStateArgs); - interleaveComma(nonBuilderStateArgsList, nonBuilderStateArgsOS); + interleave( + nonBuilderStateArgsList, + [&](StringRef name) { + nonBuilderStateArgsOS << "std::forward(" + << name << ')'; + }, + [&] { nonBuilderStateArgsOS << ", "; }); + nonBuilderStateArgs = ", " + nonBuilderStateArgs; } cWithLoc->body() << llvm::formatv(inlineCreateBody, locParamName, diff --git a/mlir/unittests/ExecutionEngine/Invoke.cpp b/mlir/unittests/ExecutionEngine/Invoke.cpp index 887db227cfc4b..312b10f28143f 100644 --- a/mlir/unittests/ExecutionEngine/Invoke.cpp +++ b/mlir/unittests/ExecutionEngine/Invoke.cpp @@ -205,7 +205,13 @@ TEST(NativeMemRefJit, SKIP_WITHOUT_JIT(BasicMemref)) { }; int64_t shape[] = {k, m}; int64_t shapeAlloc[] = {k + 1, m + 1}; - OwningMemRef a(shape, shapeAlloc, init); + // Use a large alignment to stress the case where the memref data/basePtr are + // disjoint. + int alignment = 8192; + OwningMemRef a(shape, shapeAlloc, init, alignment); + ASSERT_EQ( + (void *)(((uintptr_t)a->basePtr + alignment - 1) & ~(alignment - 1)), + a->data); ASSERT_EQ(a->sizes[0], k); ASSERT_EQ(a->sizes[1], m); ASSERT_EQ(a->strides[0], m + 1); diff --git a/mlir/unittests/IR/AttributeTest.cpp b/mlir/unittests/IR/AttributeTest.cpp index a55592db7132d..fd40404bf3008 100644 --- a/mlir/unittests/IR/AttributeTest.cpp +++ b/mlir/unittests/IR/AttributeTest.cpp @@ -477,8 +477,9 @@ TEST(SubElementTest, Nested) { {strAttr, trueAttr, falseAttr, boolArrayAttr, dictAttr})); } -// Test how many times we call copy-ctor when building an attribute. -TEST(CopyCountAttr, CopyCount) { +// Test how many times we call copy-ctor when building an attribute with the +// 'get' method. +TEST(CopyCountAttr, CopyCountGet) { MLIRContext context; context.loadDialect(); @@ -489,15 +490,35 @@ TEST(CopyCountAttr, CopyCount) { test::CopyCount::counter = 0; test::TestCopyCountAttr::get(&context, std::move(copyCount)); #ifndef NDEBUG - // One verification enabled only in assert-mode requires a copy. - EXPECT_EQ(counter1, 1); - EXPECT_EQ(test::CopyCount::counter, 1); + // One verification enabled only in assert-mode requires two copies: one for + // calling 'verifyInvariants' and one for calling 'verify' inside + // 'verifyInvariants'. + EXPECT_EQ(counter1, 2); + EXPECT_EQ(test::CopyCount::counter, 2); #else EXPECT_EQ(counter1, 0); EXPECT_EQ(test::CopyCount::counter, 0); #endif } +// Test how many times we call copy-ctor when building an attribute with the +// 'getChecked' method. +TEST(CopyCountAttr, CopyCountGetChecked) { + MLIRContext context; + context.loadDialect(); + test::CopyCount::counter = 0; + test::CopyCount copyCount("hello"); + auto loc = UnknownLoc::get(&context); + test::TestCopyCountAttr::getChecked(loc, &context, std::move(copyCount)); + int counter1 = test::CopyCount::counter; + test::CopyCount::counter = 0; + test::TestCopyCountAttr::getChecked(loc, &context, std::move(copyCount)); + // The verifiers require two copies: one for calling 'verifyInvariants' and + // one for calling 'verify' inside 'verifyInvariants'. + EXPECT_EQ(counter1, 2); + EXPECT_EQ(test::CopyCount::counter, 2); +} + // Test stripped printing using test dialect attribute. TEST(CopyCountAttr, PrintStripped) { MLIRContext context; diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt index d22afb3003e76..a46e64718dab9 100644 --- a/mlir/unittests/IR/CMakeLists.txt +++ b/mlir/unittests/IR/CMakeLists.txt @@ -6,6 +6,7 @@ add_mlir_unittest(MLIRIRTests AttrTypeReplacerTest.cpp Diagnostic.cpp DialectTest.cpp + DistinctAttributeAllocatorTest.cpp InterfaceTest.cpp IRMapping.cpp InterfaceAttachmentTest.cpp diff --git a/mlir/unittests/IR/DistinctAttributeAllocatorTest.cpp b/mlir/unittests/IR/DistinctAttributeAllocatorTest.cpp new file mode 100644 index 0000000000000..99067d09f7bed --- /dev/null +++ b/mlir/unittests/IR/DistinctAttributeAllocatorTest.cpp @@ -0,0 +1,45 @@ +//=== DistinctAttributeAllocatorTest.cpp - DistinctAttr storage alloc test ===// +// +// 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 "gtest/gtest.h" + +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/MLIRContext.h" +#include "llvm/Support/CrashRecoveryContext.h" +#include + +using namespace mlir; + +// +// Test that a DistinctAttr that is created on a separate thread does +// not have its storage deleted when the thread joins. +// +TEST(DistinctAttributeAllocatorTest, TestAttributeWellFormedAfterThreadJoin) { + MLIRContext ctx; + OpBuilder builder(&ctx); + DistinctAttr attr; + + std::thread t([&ctx, &attr]() { + attr = DistinctAttr::create(UnitAttr::get(&ctx)); + ASSERT_TRUE(attr); + }); + t.join(); + + // If the attribute storage got deleted after the thread joins (which we don't + // want) then trying to access it triggers an assert in Debug mode, and a + // crash otherwise. Run this in a CrashRecoveryContext to avoid bringing down + // the whole test suite if this test fails. Additionally, MSAN and/or TSAN + // should raise failures here if the attribute storage was deleted. + llvm::CrashRecoveryContext crc; + EXPECT_TRUE(crc.RunSafely([attr]() { (void)attr.getAbstractAttribute(); })); + EXPECT_TRUE( + crc.RunSafely([attr]() { (void)*cast(attr).getImpl(); })); + + ASSERT_TRUE(attr); +} diff --git a/mlir/unittests/Pass/CMakeLists.txt b/mlir/unittests/Pass/CMakeLists.txt index a47d2eead6180..e5dfd75606458 100644 --- a/mlir/unittests/Pass/CMakeLists.txt +++ b/mlir/unittests/Pass/CMakeLists.txt @@ -2,6 +2,7 @@ add_mlir_unittest(MLIRPassTests AnalysisManagerTest.cpp PassManagerTest.cpp PassPipelineParserTest.cpp + PassPipelineOptionsTest.cpp ) mlir_target_link_libraries(MLIRPassTests PRIVATE diff --git a/mlir/unittests/Pass/PassPipelineOptionsTest.cpp b/mlir/unittests/Pass/PassPipelineOptionsTest.cpp new file mode 100644 index 0000000000000..2e586c3c40887 --- /dev/null +++ b/mlir/unittests/Pass/PassPipelineOptionsTest.cpp @@ -0,0 +1,136 @@ +//===- PassPipelineParserTest.cpp - Pass Parser unit tests ----------------===// +// +// 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 "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "gtest/gtest.h" + +#include + +using namespace mlir; +using namespace mlir::detail; + +namespace { + +// these types are used for automatically generated code of pass +using StrPassOpt = ::mlir::Pass::Option; +using IntPassOpt = ::mlir::Pass::Option; +using BoolPassOpt = ::mlir::Pass::Option; + +// these types are used for pipeline options that we manually pass to the +// constructor +using StrOption = mlir::detail::PassOptions::Option; +using IntOption = mlir::detail::PassOptions::Option; +using BoolOption = mlir::detail::PassOptions::Option; + +const int intOptDefaultVal = 5; +const bool boolOptDefaultVal = true; + +struct SimplePassWithOptions + : public PassWrapper> { + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SimplePassWithOptions) + + SimplePassWithOptions() = default; + SimplePassWithOptions(const SimplePassWithOptions &other) + : PassWrapper(other) {} + + SimplePassWithOptions(const detail::PassOptions &options) { + copyOptionValuesFrom(options); + } + + LogicalResult initialize(MLIRContext *ctx) final { return success(); } + + void runOnOperation() override {} + +public: + StrPassOpt strOpt{*this, "str-opt", ::llvm::cl::desc("string test option"), + llvm::cl::init("")}; + IntPassOpt intOpt{*this, "int-opt", ::llvm::cl::desc("int test option"), + llvm::cl::init(intOptDefaultVal)}; + BoolPassOpt boolOpt{*this, "bool-opt", ::llvm::cl::desc("bool test option"), + llvm::cl::init(boolOptDefaultVal)}; +}; + +TEST(PassPipelineOptionsTest, CopyAllOptions) { + struct DuplicatedOtions : ::mlir::PassPipelineOptions { + StrOption strOpt{*this, "str-opt", ::llvm::cl::desc("string test option")}; + IntOption intOpt{*this, "int-opt", ::llvm::cl::desc("int test option"), + llvm::cl::init(intOptDefaultVal)}; + BoolOption boolOpt{*this, "bool-opt", ::llvm::cl::desc("bool test option"), + llvm::cl::init(boolOptDefaultVal)}; + }; + + const auto expectedStrVal = "test1"; + const auto expectedIntVal = -intOptDefaultVal; + const auto expectedBoolVal = !boolOptDefaultVal; + + DuplicatedOtions options; + options.strOpt.setValue(expectedStrVal); + options.intOpt.setValue(expectedIntVal); + options.boolOpt.setValue(expectedBoolVal); + + const auto &pass = std::make_unique(options); + + EXPECT_EQ(pass->strOpt.getValue(), expectedStrVal); + EXPECT_EQ(pass->intOpt.getValue(), expectedIntVal); + EXPECT_EQ(pass->boolOpt.getValue(), expectedBoolVal); +} + +TEST(PassPipelineOptionsTest, CopyMatchedOptions) { + struct SomePipelineOptions + : ::mlir::PassPipelineOptions { + StrOption strOpt{*this, "str-opt", ::llvm::cl::desc("string test option")}; + IntOption intOpt{*this, "int-opt", ::llvm::cl::desc("int test option")}; + StrOption anotherStrOpt{ + *this, "another-str-pipeline-opt", + ::llvm::cl::desc("there is no such option in SimplePassWithOptions"), + llvm::cl::init("anotherOptVal")}; + IntOption anotherIntOpt{ + *this, "another-int-pipeline-opt", + ::llvm::cl::desc("there is no such option in SimplePassWithOptions"), + llvm::cl::init(10)}; + }; + + const auto expectedStrVal = "test2"; + const auto expectedIntVal = -intOptDefaultVal; + + SomePipelineOptions options; + options.strOpt.setValue(expectedStrVal); + options.intOpt.setValue(expectedIntVal); + + const auto pass = std::make_unique(options); + + EXPECT_EQ(pass->strOpt.getValue(), expectedStrVal); + EXPECT_EQ(pass->intOpt.getValue(), expectedIntVal); + EXPECT_EQ(pass->boolOpt.getValue(), boolOptDefaultVal); +} + +TEST(PassPipelineOptionsTest, NoMatchedOptions) { + struct SomePipelineOptions + : ::mlir::PassPipelineOptions { + StrOption anotherStrOpt{ + *this, "another-str-pipeline-opt", + ::llvm::cl::desc("there is no such option in SimplePassWithOptions"), + llvm::cl::init("anotherOptVal")}; + IntOption anotherIntOpt{ + *this, "another-int-pipeline-opt", + ::llvm::cl::desc("there is no such option in SimplePassWithOptions"), + llvm::cl::init(10)}; + }; + + SomePipelineOptions options; + const auto pass = std::make_unique(options); + + EXPECT_EQ(pass->strOpt.getValue(), ""); + EXPECT_EQ(pass->intOpt.getValue(), intOptDefaultVal); + EXPECT_EQ(pass->boolOpt.getValue(), boolOptDefaultVal); +} + +} // namespace diff --git a/offload/plugins-nextgen/common/src/Utils/ELF.cpp b/offload/plugins-nextgen/common/src/Utils/ELF.cpp index dfec55432f202..b0ee1984c42ce 100644 --- a/offload/plugins-nextgen/common/src/Utils/ELF.cpp +++ b/offload/plugins-nextgen/common/src/Utils/ELF.cpp @@ -60,23 +60,30 @@ static Expected checkMachineImpl(const object::ELFObjectFile &ELFObj, uint16_t EMachine) { const auto Header = ELFObj.getELFFile().getHeader(); if (Header.e_type != ET_EXEC && Header.e_type != ET_DYN) - return createError("Only executable ELF files are supported"); + return createError("only executable ELF files are supported"); if (Header.e_machine == EM_AMDGPU) { if (Header.e_ident[EI_OSABI] != ELFOSABI_AMDGPU_HSA) - return createError("Invalid AMD OS/ABI, must be AMDGPU_HSA"); + return createError("invalid AMD OS/ABI, must be AMDGPU_HSA"); if (Header.e_ident[EI_ABIVERSION] != ELFABIVERSION_AMDGPU_HSA_V5 && Header.e_ident[EI_ABIVERSION] != ELFABIVERSION_AMDGPU_HSA_V6) - return createError("Invalid AMD ABI version, must be version 5 or above"); + return createError("invalid AMD ABI version, must be version 5 or above"); if ((Header.e_flags & EF_AMDGPU_MACH) < EF_AMDGPU_MACH_AMDGCN_GFX700 || (Header.e_flags & EF_AMDGPU_MACH) > EF_AMDGPU_MACH_AMDGCN_GFX9_4_GENERIC) - return createError("Unsupported AMDGPU architecture"); + return createError("unsupported AMDGPU architecture"); } else if (Header.e_machine == EM_CUDA) { - if (~Header.e_flags & EF_CUDA_64BIT_ADDRESS) - return createError("Invalid CUDA addressing mode"); - if ((Header.e_flags & EF_CUDA_SM) < EF_CUDA_SM35) - return createError("Unsupported NVPTX architecture"); + if (Header.e_ident[EI_ABIVERSION] == ELFABIVERSION_CUDA_V1) { + if (~Header.e_flags & EF_CUDA_64BIT_ADDRESS) + return createError("invalid CUDA addressing mode"); + if ((Header.e_flags & EF_CUDA_SM) < EF_CUDA_SM35) + return createError("unsupported NVPTX architecture"); + } else if (Header.e_ident[EI_ABIVERSION] == ELFABIVERSION_CUDA_V2) { + if ((Header.e_flags & EF_CUDA_SM_MASK) < EF_CUDA_SM100) + return createError("unsupported NVPTX architecture"); + } else { + return createError("invalid CUDA ABI version"); + } } return Header.e_machine == EMachine; diff --git a/offload/plugins-nextgen/cuda/src/rtl.cpp b/offload/plugins-nextgen/cuda/src/rtl.cpp index b787376eb1770..71a28fadfd81d 100644 --- a/offload/plugins-nextgen/cuda/src/rtl.cpp +++ b/offload/plugins-nextgen/cuda/src/rtl.cpp @@ -1442,7 +1442,11 @@ struct CUDAPluginTy final : public GenericPluginTy { return ElfOrErr.takeError(); // Get the numeric value for the image's `sm_` value. - auto SM = ElfOrErr->getPlatformFlags() & ELF::EF_CUDA_SM; + const auto Header = ElfOrErr->getELFFile().getHeader(); + unsigned SM = + Header.e_ident[ELF::EI_ABIVERSION] == ELF::ELFABIVERSION_CUDA_V1 + ? Header.e_flags & ELF::EF_CUDA_SM + : (Header.e_flags & ELF::EF_CUDA_SM_MASK) >> ELF::EF_CUDA_SM_OFFSET; CUdevice Device; CUresult Res = cuDeviceGet(&Device, DeviceId); diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index f62cabee6ea84..197cf54765285 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -106,12 +106,15 @@ class kmp_stats_list; // OMPD_SKIP_HWLOC used in libompd/omp-icv.cpp to avoid OMPD depending on hwloc #if KMP_USE_HWLOC && KMP_AFFINITY_SUPPORTED && !defined(OMPD_SKIP_HWLOC) #include "hwloc.h" +#define KMP_HWLOC_ENABLED 1 #ifndef HWLOC_OBJ_NUMANODE #define HWLOC_OBJ_NUMANODE HWLOC_OBJ_NODE #endif #ifndef HWLOC_OBJ_PACKAGE #define HWLOC_OBJ_PACKAGE HWLOC_OBJ_SOCKET #endif +#else +#define KMP_HWLOC_ENABLED 0 #endif #if KMP_ARCH_X86 || KMP_ARCH_X86_64 @@ -692,10 +695,10 @@ typedef BOOL (*kmp_SetThreadGroupAffinity_t)(HANDLE, const GROUP_AFFINITY *, extern kmp_SetThreadGroupAffinity_t __kmp_SetThreadGroupAffinity; #endif /* KMP_OS_WINDOWS */ -#if KMP_USE_HWLOC && !defined(OMPD_SKIP_HWLOC) +#if KMP_HWLOC_ENABLED extern hwloc_topology_t __kmp_hwloc_topology; extern int __kmp_hwloc_error; -#endif +#endif // KMP_HWLOC_ENABLED extern size_t __kmp_affin_mask_size; #define KMP_AFFINITY_CAPABLE() (__kmp_affin_mask_size > 0) @@ -804,10 +807,10 @@ class KMPAffinity { static void destroy_api(); enum api_type { NATIVE_OS -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED , HWLOC -#endif +#endif // KMP_HWLOC_ENABLED }; virtual api_type get_api_type() const { KMP_ASSERT(0); @@ -876,9 +879,9 @@ enum affinity_top_method { affinity_top_method_group, #endif /* KMP_GROUP_AFFINITY */ affinity_top_method_flat, -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED affinity_top_method_hwloc, -#endif +#endif // KMP_HWLOC_ENABLED affinity_top_method_default }; @@ -1145,9 +1148,9 @@ typedef struct kmp_allocator_t { omp_alloctrait_value_t target_access; omp_alloctrait_value_t atomic_scope; size_t part_size; -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED omp_alloctrait_value_t membind; -#endif +#endif // KMP_HWLOC_ENABLED } kmp_allocator_t; extern omp_allocator_handle_t __kmpc_init_allocator(int gtid, @@ -2107,12 +2110,12 @@ typedef struct dispatch_shared_info { #if KMP_USE_HIER_SCHED void *hier; #endif -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // When linking with libhwloc, the ORDERED EPCC test slows down on big // machines (> 48 cores). Performance analysis showed that a cache thrash // was occurring and this padding helps alleviate the problem. char padding[64]; -#endif +#endif // KMP_HWLOC_ENABLED } dispatch_shared_info_t; typedef struct kmp_disp { diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index a6065fe792d55..50389502d3b45 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -19,13 +19,13 @@ #if KMP_USE_HIER_SCHED #include "kmp_dispatch_hier.h" #endif -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // Copied from hwloc #define HWLOC_GROUP_KIND_INTEL_MODULE 102 #define HWLOC_GROUP_KIND_INTEL_TILE 103 #define HWLOC_GROUP_KIND_INTEL_DIE 104 #define HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP 220 -#endif +#endif // KMP_HWLOC_ENABLED #include // The machine topology @@ -1438,7 +1438,7 @@ void KMPAffinity::pick_api() { KMPAffinity *affinity_dispatch; if (picked_api) return; -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // Only use Hwloc if affinity isn't explicitly disabled and // user requests Hwloc topology method if (__kmp_affinity_top_method == affinity_top_method_hwloc && @@ -1446,7 +1446,7 @@ void KMPAffinity::pick_api() { affinity_dispatch = new KMPHwlocAffinity(); __kmp_hwloc_available = true; } else -#endif +#endif // KMP_HWLOC_ENABLED { affinity_dispatch = new KMPNativeAffinity(); } @@ -1697,7 +1697,7 @@ kmp_affin_mask_t *__kmp_affin_fullMask = NULL; // Original mask is a subset of full mask in multiple processor groups topology kmp_affin_mask_t *__kmp_affin_origMask = NULL; -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED static inline bool __kmp_hwloc_is_cache_type(hwloc_obj_t obj) { #if HWLOC_API_VERSION >= 0x00020000 return hwloc_obj_type_is_cache(obj->type); @@ -2005,7 +2005,7 @@ static bool __kmp_affinity_create_hwloc_map(kmp_i18n_id_t *const msg_id) { __kmp_topology->sort_ids(); return true; } -#endif // KMP_USE_HWLOC +#endif // KMP_HWLOC_ENABLED // If we don't know how to retrieve the machine's processor topology, or // encounter an error in doing so, this routine is called to form a "flat" @@ -4845,7 +4845,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) { // In the default code path, errors are not fatal - we just try using // another method. We only emit a warning message if affinity is on, or the // verbose flag is set, an the nowarnings flag was not set. -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED if (!success && __kmp_affinity_dispatch->get_api_type() == KMPAffinity::HWLOC) { if (!__kmp_hwloc_error) { @@ -4857,7 +4857,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) { KMP_INFORM(AffIgnoringHwloc, env_var); } } -#endif +#endif // KMP_HWLOC_ENABLED #if KMP_ARCH_X86 || KMP_ARCH_X86_64 if (!success) { @@ -4905,7 +4905,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) { // If the user has specified that a paricular topology discovery method is to be // used, then we abort if that method fails. The exception is group affinity, // which might have been implicitly set. -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED else if (__kmp_affinity_top_method == affinity_top_method_hwloc) { KMP_ASSERT(__kmp_affinity_dispatch->get_api_type() == KMPAffinity::HWLOC); success = __kmp_affinity_create_hwloc_map(&msg_id); @@ -4914,7 +4914,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) { KMP_FATAL(MsgExiting, __kmp_i18n_catgets(msg_id)); } } -#endif // KMP_USE_HWLOC +#endif // KMP_HWLOC_ENABLED #if KMP_ARCH_X86 || KMP_ARCH_X86_64 else if (__kmp_affinity_top_method == affinity_top_method_x2apicid || @@ -5308,12 +5308,12 @@ void __kmp_affinity_uninitialize(void) { __kmp_free(__kmp_osid_to_hwthread_map); __kmp_osid_to_hwthread_map = NULL; } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED if (__kmp_hwloc_topology != NULL) { hwloc_topology_destroy(__kmp_hwloc_topology); __kmp_hwloc_topology = NULL; } -#endif +#endif // KMP_HWLOC_ENABLED if (__kmp_hw_subset) { kmp_hw_subset_t::deallocate(__kmp_hw_subset); __kmp_hw_subset = nullptr; diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h index dc3191caae634..fa69585f7e2d5 100644 --- a/openmp/runtime/src/kmp_affinity.h +++ b/openmp/runtime/src/kmp_affinity.h @@ -18,7 +18,7 @@ #include #if KMP_AFFINITY_SUPPORTED -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED class KMPHwlocAffinity : public KMPAffinity { public: class Mask : public KMPAffinity::Mask { @@ -109,7 +109,7 @@ class KMPHwlocAffinity : public KMPAffinity { } return error; } -#endif +#endif // KMP_OS_WINDOWS int get_proc_group() const override { int group = -1; #if KMP_OS_WINDOWS @@ -191,7 +191,7 @@ class KMPHwlocAffinity : public KMPAffinity { } api_type get_api_type() const override { return HWLOC; } }; -#endif /* KMP_USE_HWLOC */ +#endif /* KMP_HWLOC_ENABLED */ #if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ KMP_OS_AIX diff --git a/openmp/runtime/src/kmp_alloc.cpp b/openmp/runtime/src/kmp_alloc.cpp index 051f88c5a0996..d43daefb6ef1e 100644 --- a/openmp/runtime/src/kmp_alloc.cpp +++ b/openmp/runtime/src/kmp_alloc.cpp @@ -14,7 +14,7 @@ #include "kmp_io.h" #include "kmp_wrapper_malloc.h" -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED #if HWLOC_API_VERSION > 0x00020300 #define KMP_HWLOC_LOCATION_TYPE_CPUSET HWLOC_LOCATION_TYPE_CPUSET #elif HWLOC_API_VERSION == 0x00020300 @@ -26,7 +26,7 @@ enum hwloc_memattr_id_e { HWLOC_MEMATTR_ID_CAPACITY }; #endif -#endif // KMP_USE_HWLOC +#endif // KMP_HWLOC_ENABLED // Disable bget when it is not used #if KMP_USE_BGET @@ -1545,7 +1545,7 @@ void __kmp_fini_memkind() { #endif } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED static bool __kmp_is_hwloc_membind_supported(hwloc_membind_policy_t policy) { #if HWLOC_API_VERSION >= 0x00020300 const hwloc_topology_support *support; @@ -1561,7 +1561,7 @@ static bool __kmp_is_hwloc_membind_supported(hwloc_membind_policy_t policy) { return false; #else return false; -#endif +#endif // KMP_HWLOC_ENABLED } void *__kmp_hwloc_alloc_membind(hwloc_memattr_id_e attr, size_t size, @@ -1611,7 +1611,7 @@ void *__kmp_hwloc_membind_policy(omp_memspace_handle_t ms, size_t size, return NULL; #endif } -#endif // KMP_USE_HWLOC +#endif // KMP_HWLOC_ENABLED void __kmp_init_target_mem() { *(void **)(&kmp_target_alloc_host) = KMP_DLSYM("llvm_omp_target_alloc_host"); @@ -1680,13 +1680,13 @@ omp_allocator_handle_t __kmpc_init_allocator(int gtid, omp_memspace_handle_t ms, al->fb_data = RCAST(kmp_allocator_t *, traits[i].value); break; case omp_atk_partition: -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED al->membind = (omp_alloctrait_value_t)traits[i].value; KMP_DEBUG_ASSERT(al->membind == omp_atv_environment || al->membind == omp_atv_nearest || al->membind == omp_atv_blocked || al->membind == omp_atv_interleaved); -#endif +#endif // KMP_HWLOC_ENABLED al->memkind = RCAST(void **, traits[i].value); break; case omp_atk_pin_device: @@ -1980,7 +1980,7 @@ void *__kmp_alloc(int gtid, size_t algn, size_t size, } } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED if (__kmp_hwloc_available) { if (__kmp_is_hwloc_membind_supported(HWLOC_MEMBIND_BIND)) { if (allocator < kmp_max_mem_alloc) { @@ -2074,7 +2074,7 @@ void *__kmp_alloc(int gtid, size_t algn, size_t size, ptr = hwloc_alloc(__kmp_hwloc_topology, desc.size_a); } } else { -#endif +#endif // KMP_HWLOC_ENABLED if (__kmp_memkind_available) { if (allocator < kmp_max_mem_alloc) { // pre-defined allocator @@ -2201,9 +2201,9 @@ void *__kmp_alloc(int gtid, size_t algn, size_t size, KMP_ASSERT(0); // abort fallback requested } // no sense to look for another fallback because of same internal alloc } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED } -#endif +#endif // KMP_HWLOC_ENABLED KE_TRACE(10, ("__kmp_alloc: T#%d %p=alloc(%d)\n", gtid, ptr, desc.size_a)); if (ptr == NULL) return NULL; @@ -2339,7 +2339,7 @@ void ___kmpc_free(int gtid, void *ptr, omp_allocator_handle_t allocator) { kmp_target_unlock_mem(desc.ptr_alloc, device); } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED if (__kmp_hwloc_available) { if (oal > kmp_max_mem_alloc && al->pool_size > 0) { kmp_uint64 used = @@ -2349,7 +2349,7 @@ void ___kmpc_free(int gtid, void *ptr, omp_allocator_handle_t allocator) { } hwloc_free(__kmp_hwloc_topology, desc.ptr_alloc, desc.size_a); } else { -#endif +#endif // KMP_HWLOC_ENABLED if (__kmp_memkind_available) { if (oal < kmp_max_mem_alloc) { // pre-defined allocator @@ -2378,9 +2378,9 @@ void ___kmpc_free(int gtid, void *ptr, omp_allocator_handle_t allocator) { } __kmp_thread_free(__kmp_thread_from_gtid(gtid), desc.ptr_alloc); } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED } -#endif +#endif // KMP_HWLOC_ENABLED } /* If LEAK_MEMORY is defined, __kmp_free() will *not* free memory. It causes diff --git a/openmp/runtime/src/kmp_dispatch.h b/openmp/runtime/src/kmp_dispatch.h index cf19eb52662ce..f161a801700f4 100644 --- a/openmp/runtime/src/kmp_dispatch.h +++ b/openmp/runtime/src/kmp_dispatch.h @@ -182,12 +182,12 @@ template struct dispatch_shared_info_template { #if KMP_USE_HIER_SCHED kmp_hier_t *hier; #endif -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // When linking with libhwloc, the ORDERED EPCC test slowsdown on big // machines (> 48 cores). Performance analysis showed that a cache thrash // was occurring and this padding helps alleviate the problem. char padding[64]; -#endif +#endif // KMP_HWLOC_ENABLED }; /* ------------------------------------------------------------------------ */ diff --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp index 87c0a66a16c0a..f19d83bb5d053 100644 --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/runtime/src/kmp_global.cpp @@ -250,10 +250,10 @@ enum mic_type __kmp_mic_type = non_mic; KMPAffinity *__kmp_affinity_dispatch = NULL; -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED int __kmp_hwloc_error = FALSE; hwloc_topology_t __kmp_hwloc_topology = NULL; -#endif +#endif // KMP_HWLOC_ENABLED #if KMP_OS_WINDOWS #if KMP_GROUP_AFFINITY diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp index 392a02ebbd9aa..d806b02ade4df 100644 --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -1069,10 +1069,10 @@ static void __kmp_stg_print_warnings(kmp_str_buf_t *buffer, char const *name, static void __kmp_stg_parse_nesting_mode(char const *name, char const *value, void *data) { __kmp_stg_parse_int(name, value, 0, INT_MAX, &__kmp_nesting_mode); -#if KMP_AFFINITY_SUPPORTED && KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED if (__kmp_nesting_mode > 0) __kmp_affinity_top_method = affinity_top_method_hwloc; -#endif +#endif // KMP_HWLOC_ENABLED } // __kmp_stg_parse_nesting_mode static void __kmp_stg_print_nesting_mode(kmp_str_buf_t *buffer, @@ -3291,11 +3291,11 @@ static void __kmp_stg_parse_topology_method(char const *name, char const *value, if (__kmp_str_match("all", 1, value)) { __kmp_affinity_top_method = affinity_top_method_all; } -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED else if (__kmp_str_match("hwloc", 1, value)) { __kmp_affinity_top_method = affinity_top_method_hwloc; } -#endif +#endif // KMP_HWLOC_ENABLED #if KMP_ARCH_X86 || KMP_ARCH_X86_64 else if (__kmp_str_match("cpuid_leaf31", 12, value) || __kmp_str_match("cpuid 1f", 8, value) || @@ -3399,11 +3399,11 @@ static void __kmp_stg_print_topology_method(kmp_str_buf_t *buffer, break; #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED case affinity_top_method_hwloc: value = "hwloc"; break; -#endif +#endif // KMP_HWLOC_ENABLED case affinity_top_method_cpuinfo: value = "cpuinfo"; @@ -6289,7 +6289,7 @@ void __kmp_env_initialize(char const *string) { #if KMP_AFFINITY_SUPPORTED if (!TCR_4(__kmp_init_middle)) { -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // Force using hwloc when either tiles or numa nodes requested within // KMP_HW_SUBSET or granularity setting and no other topology method // is requested @@ -6304,12 +6304,12 @@ void __kmp_env_initialize(char const *string) { if (__kmp_affinity.gran == KMP_HW_NUMA || __kmp_affinity.gran == KMP_HW_TILE) __kmp_affinity_top_method = affinity_top_method_hwloc; -#endif +#endif // KMP_HWLOC_ENABLED // Determine if the machine/OS is actually capable of supporting // affinity. const char *var = "KMP_AFFINITY"; KMPAffinity::pick_api(); -#if KMP_USE_HWLOC +#if KMP_HWLOC_ENABLED // If Hwloc topology discovery was requested but affinity was also disabled, // then tell user that Hwloc request is being ignored and use default // topology discovery method. @@ -6318,7 +6318,7 @@ void __kmp_env_initialize(char const *string) { KMP_WARNING(AffIgnoringHwloc, var); __kmp_affinity_top_method = affinity_top_method_all; } -#endif +#endif // KMP_HWLOC_ENABLED if (__kmp_affinity.type == affinity_disabled) { KMP_AFFINITY_DISABLE(); } else if (!KMP_AFFINITY_CAPABLE()) {